20200621のlaravelに関する記事は10件です。

【Laravel】テンプレートの書き方

概要

LaravelのMVCのうちのビュー周辺について説明するよ
つまり、テンプレートの書き方だね
初心者向け程度の内容だよ
【Laravel】コントローラの書き方と一緒に読むといいよ

ビューの呼び出し

コントローラ側でview()が呼ばれると、引数に与えられたテンプレートがレンダリングされてブラウザに表示されるよ
例えば、view('welcome')の場合、resourcesフォルダ内のviewフォルダの中にあるwelcome.blade.phpまたはwelcome.phpというファイルが呼び出される
2つともファイルがあると拡張子がblade.phpの方が呼び出される

viewフォルダの中にさらにフォルダを作りその中にテンプレートを作ると、
  view('フォルダ名.テンプレート名')
のように呼び出せばいい

テンプレートの例

  • htmlファイルと同じように書く
resources/view/hello.blade.php
<html>
<head>
    <title>Hello</title>
</head>
<body>
    <h1>Hello</h1>
    <p>Hello World</p>
    <p>Hello Laravel</p>
</body>
</html>

これでもいいんだけど、フレームワークらしくないよね
そこで

  • Bladeを使う
resources/view/hello.blade.php
@extends('template')
@section('title', 'Hello')
@section('greeting')
    <p>Hello World</p>
    <p>Hello Laravel</p>
@endsection
resources/view/template.blade.php
<html>
<head>
    <title>@yield('title')</title>
</head>
<body>
    <h1>Hello</h1>
    @yield('greeting')
</body>
</html>

@で書かれたものはディレクティブと呼ばれているよ
extendsディレクティブで「template.blade.phpを使うよ」と宣言して、
yieldディレクティブのところに、sectionディレクティブで設定したものが入る感じだよ

ディレクティブには、

  • section
  • yield
  • component
  • include

のような組み込むものがあったり

  • if
  • for
  • foreach
  • while
  • switch

のような制御構文のものがあったり

  • csrf
  • method
  • error

のようなフォーム関連のものがあるよ
使い方や説明はReadoubleに書いてあるから見ておくといいよ(ここでは詳しくは説明しない)

値の埋め込み

resources/view/hello.blade.php
@extends('template')
@section('title', 'Hello')
@section('greeting')
    <p>Hello World</p>
    @if ($name != null)
    <p>Hello {{$name}}</p>
    @endif
@endsection

上のように{{ }}の中に変数や関数を書くことで値を埋め込めることができる
例えば、コントローラ側で
  view('hello',['name'=>'Laravel'])
とあったら、{{$name}}の部分にLaravelが表示されることになるよ

おわり

今回はここまで
ディレクティブの部分は全部説明すると長くなりそうだったのでReadoubleに丸投げ(手抜き)
要は

  • view()でテンプレートを呼び出してレンダリング
  • ディレクティブを使いこなそう
  • {{ }}内に変数や関数を書いて値を埋め込む

ということ
以上!

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

LaravelのCollectionのsortBy()メソッドを使うときの注意点

概要

  • インデックス配列を、sortBy() すると、順番が入れ替わる場合に連想配列になります。
  • 順序が入れ替わらない場合は、インデックス配列のままです。
  • APIなどで配列をJSONなどに出力すると結果によって、フォーマットが崩れてしまうケースがあるので注意が必要です。
  • 意識してインデックス配列にする場合は、 values() メソッドを利用し配列の番号を振り直し、インデックス配列に強制します。
sample.php
$array = [
    [
      'name' => 'ryoma',
      'age' => 33,
    ], 
    [
      'name' => 'taro',
      'age' => 22,
    ],
];

// 変更なし配列そのまま 
echo json_encode($array);

// [{"name":"ryoma","age":33},{"name":"taro","age":22}]


// sortBy で前後関係が入れ替わらないケース (インデックス配列)
echo json_encode(collect($array)->sortBy('name'));

// [{"name":"ryoma","age":33},{"name":"taro","age":22}]


// sortBy で前後関係が入れ替わるケース (連想配列になる)
echo json_encode(collect($array)->sortBy('age'));

// {"1":{"name":"taro","age":22},"0":{"name":"ryoma","age":33}}


// 連想配列になるケースをvalues() で 整数を振り直して、インデックス配列に強制
echo json_encode(collect($array)->sortBy('age')->values());

// [{"name":"taro","age":22},{"name":"ryoma","age":33}]

まとめ

  • sortBy() 使って インデックス配列で返却して欲しいときは、values()を使いましょう
  • \(^o^)/
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】コントローラの書き方

概要

Laravelのコントローラ周辺について説明するよ
初心者向けの内容だよ
【Laravel】ルーティングの書き方と一緒に読むといいよ

コントローラ

コントローラとは、アプリケーションの処理を実装する部分だよ
クライアントからアクセスがあると、ルーティングによって、「○○というアドレスがきたら××という処理を行う」ということを決めるんだけど、この「××という処理」を書いているものがコントローラだよ
コントローラはクラスで表されていて、アクションというメソッドで書かれたものの中に具体的な処理を書いていく

基本

コントローラを作成するにはartisanコマンドを使う

% php artisan make:controller コントローラ名

コントローラ名は大文字で始まって、○○Controllerという名前にするのが一般的だね

% php artisan make:controller HelloController

例えば、上のようなコマンドを打つと以下のようなコントローラができる

app/Http/Controllers/HelloController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class HelloController extends Controller
{
    //
}

?>

※以下namespaceやuseは省略

例えばindexというアクションを書いてみる

app/Http/Controllers/HelloController.php
class HelloController extends Controller
{
    public function index()
    {
        $param = ['msg' => 'Hello'];
        return view('welcome', $param);
    }
}

アクション内でreturnするのは、主にview()やredirect()だね
view()は引数にテンプレート名やパラメータをとって、ブラウザにビューを表示させる
リダイレクトは例えばredirect('/hello/index')って感じ

上の例でいうと、indexの引数は何もないけれど、ルートにパラメータがある場合は引数を設定する
ただし、'http://.../index?id=1'のように?より後ろのパラメータは引数設定しても取得できない
この場合は以下のように引数にRequestオブジェクトの\$requestを設定して、$request->idのように取得すればいい

app/Http/Controllers/HelloController.php
class HelloController extends Controller
{
    public function index(Request $request)
    {
        $param = ['msg' => 'Hello', 'id' => $request->id];
        return view('welcome', $param);
    }
}

おわり

今回はここまで
あんまり説明することがなかったね
それだけ単純だってこと
次はビューやテンプレートについて話していこうかな

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

laravelのbref を利用し、lambda にデプロイする

はじめに

laravelで制作したアプリをサーバーレス用ライブラリbrefを使い、AWSにデプロイしました。デプロイは、serverless frameworkがやってくれます。

ちなみに、参考にした先輩の記事はこちら。

Laravelのサーバレス用ライブラリbrefを使い、lambdaでhello world
PHP

https://qiita.com/umihico/items/64fcf159f68ebd866170

アプリ作成とbrefインストール

$ composer create-project --prefer-dist laravel/laravel laravel-demo #プロジェクト作成
$ cd laravel-demo
$ composer require bref/bref #肝のbrefインストール

編集するファイル

.env

- SESSION_DRIVER=file
+ SESSION_DRIVER=array
+ VIEW_COMPILED_PATH=/tmp/storage/framework/views
config/logginf.php
        'stack' => [
             'driver' => 'stack',
-            'channels' => ['single'],  # <= 削除
+            'channels' => ['stderr'],  # <= 挿入
             'ignore_exceptions' => false,
         ],
app/Providers/AppServiceProvider.php
     public function boot()
     {
-        //
+        if (!is_dir(config('view.compiled'))) {  
+            mkdir(config('view.compiled'), 0755, true);
+        }
     }
 }

serverless.ymlの編集

serverless.yml
service: laravel-demo

provider:
  name: aws
  region: ap-northeast-1
  runtime: provided

plugins:
  - ./vendor/bref/bref

package:
  exclude:
    - node_modules/**
    - public/storage
    - storage/**
    - tests/**

functions:
  website:
    handler: public/index.php
    timeout: 28 # in seconds (API Gateway has a timeout of 29 seconds)
    layers:
      - ${bref:layer.php-73-fpm}
    events:
      - http: 'ANY /'
      - http: 'ANY /{proxy+}'
  artisan:
    handler: artisan
    timeout: 120 # in seconds
    layers:
      - ${bref:layer.php-73} # PHP
      - ${bref:layer.console} # The "console" layer

artisanコマンド用関数は、ローカルでしか実行しないならコメントアウトしても構いません。

デプロイ

デプロイコマンドを叩く前に、必ずphp artisan config:clearしましょう。

$ php artisan config:clear
Configuration cache cleared!
$ sls deploy

これで完了です!

おわりに

サーバーレスフレームワークを利用すれば、サーバーを持つ必要がなく、サーバー代もかなり節約できるので、おすすめです。

参考記事

https://bref.sh/docs/frameworks/laravel.html

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

環境ごとに.envファイルを切り替える

はじめに

laravelで環境ごとに.envファイルを切り替えるというところで、結構詰まったので、メモとして残しておく。
特に、最後の注意の部分はぜひ読んで欲しいです。

bootstrap/app.php編集

bootstrap/app.php
+ $app->loadEnvironmentFrom('.env.' . ((getenv("ENV") ? getenv("ENV") : "local")));  #<= 追記

.env ファイルのコピーを作成

$ cp .env .env.local
$ cp .env .env.stg

作成したファイルの中身を変更

env.local
APP_NAME=Laravel-local
env.stg
APP_NAME=Laravel-stg

ルーティングを設定

ルートパスでAPP_NAMEが表示されるようにする。

routes/web.php
Route::get('/', function () {
    return env('APP_NAME');
});

検証

$ export ENV=stg 
$ php artisan serve
Laravel development server started: http://127.0.0.1:8000 

localhost:8000にアクセスして、laravel-stgが表示されれば成功です。

環境を変えたいときは、

$ export ENV=local

とするだけ。

これで完了です!

注意

もし、上記を行っても、表示されない。真っ白な画面が表示されるだけという状態であれば、以下のコマンドを実行。

$ php artisan config:clear
Configuration cache cleared!

.envファイルに環境変数が設定されているにも関わらず、env関数がnullを返す場合があります。それは、設定ファイルがキャッシュされている場合です。「設定ファイルがキャッシュされると、.envファイルはロードされなくなり、env関数の呼び出しは全てnullを返す」仕様らしい。

詳しくは以下の記事

Laravelのenv関数で値が取得できない原因と対策
https://qiita.com/yamaji_daisuke/items/746e1e5ec3487fc88c3e

おわりに

駆け出しエンジニアからすると、環境設定系の記述や編集は、理解が難しく、避けがちですが、少しずつわかってくると楽しいもんですね。

参考記事

[Laravel 5.5] 読み込む.envファイルを環境ごとに切り替える
https://qiita.com/takaday/items/b992c7d8cd69343b6626

Laravelでenvやgetenvで環境変数が読めない現象について
https://qiita.com/hiroykam/items/5f1a44cf94173476a12e

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

Laravelログイン機能の実装について

はじめに

草野と申します。
今回の投稿は、プログラミングスクールを卒業後、同期生に声をかけチームを作り、行っている開発についてアウトプットを行います。自分用のメモのため、文章は拙いですが、少しでも初学者の助けになればと考えています
内容は、表題にもあるとおり、チーム開発によるアプリのログイン機能実装についてです。未熟な点も多いと思います。不備等ありましたらご指摘ください。随時改善して行こうと思います。ちなみに私は、Railsを学びLaravelを次に学んでいるという状況です。

Laravelの導入方法について

Laravelの導入方法については以下の記事を参考にさせて頂きました。

完成品

Image from Gyazo

Image from Gyazo

ログイン機能実装手順

※今回は% php artisan migrateまで行ったあとからの手順になります。DBはmysqlを使用しています。

1.環境設定

  • laravel/uiライブラリのインストール
  • ログイン、新規登録周りファイルのインストール(ここでvueを取り入れています)
  • Node.jsのインストール
  • npmのインストール

2.日本語化

  • config.phpファイル内の設定変更
  • 日本語フォルダインストール
  • ビューの日本語化を行うため、ja.jsonファイル作成

3.ユーザー新規登録の編集

  • usersテーブルへカラムの追加
  • ビューへinputを追加
  • コントローラー編集
  • モデル編集

環境設定

ターミナルで以下のコマンドを実行します。
まずlaravel/uiライブラリをインストールします。

ターミナル
% composer require laravel/ui
  • 変更されるファイル
    • composer.json
    • composer.lock

ログイン、新規登録周りファイルのインストールします。(ここでvueを取り入れています)

ターミナル
% php artisan ui vue --auth
  • 追加されるファイル
    • app/Http/Controllers/HomeController.php
    • resources/js/components/ExampleComponent.vue
    • resources/sass/_variables.scss
    • resources/views/auth/login.blade.php
    • resources/views/auth/passwords/email.blade.php
    • resources/views/auth/passwords/reset.blade.php
    • resources/views/auth/register.blade.php
    • resources/views/auth/verify.blade.php
    • resources/views/home.blade.php
    • resources/views/layouts/app.blade.php
  • 変更されるファイル
    • package.json
    • resources/js/app.js
    • resources/js/bootstrap.js
    • resources/sass/app.scss
    • routes/web.php
    • webpack.mix.js

Node.jsを導入するに当たり、サイトからダウンロードするやり方をしている人(これはYouTubeで見ました)もいましたが、バージョン管理などを行うことを考えるとnodebrewをインストールした方が良いです。

ターミナル
% brew install nodebrew

Nodebrewのインストールを確認します。

ターミナル
% nodebrew -v
ターミナル
nodebrew 1.0.1

Usage:
    nodebrew help                         Show this message
    nodebrew install <version>            Download and install <version> (from binary)
    nodebrew compile <version>            Download and install <version> (from source)
    nodebrew install-binary <version>     Alias of `install` (For backword compatibility)
    nodebrew uninstall <version>          Uninstall <version>
    nodebrew use <version>                Use <version>
    nodebrew list                         List installed versions
    nodebrew ls                           Alias for `list`
    nodebrew ls-remote                    List remote versions
    nodebrew ls-all                       List remote and installed versions
    nodebrew alias <key> <value>          Set alias
    nodebrew unalias <key>                Remove alias
    nodebrew clean <version> | all        Remove source file
    nodebrew selfupdate                   Update nodebrew
    nodebrew migrate-package <version>    Install global NPM packages contained in <version> to current version
    nodebrew exec <version> -- <command>  Execute <command> using specified <version>

Example:
    # install
    nodebrew install v8.9.4

    # use a specific version number
    nodebrew use v8.9.4

次にNode.jsのインストールします。

ターミナル
% nodebrew install-binary stable

すると下記のようなエラーが出ました。

ターミナル
Fetching: https://nodejs.org/dist/v14.4.0/node-v14.4.0-darwin-x64.tar.gz
Warning: Failed to create the file 
Warning: /Users/kyousuke_kusano/.nodebrew/src/v14.4.0/node-v14.4.0-darwin-x64.t
Warning: ar.gz: No such file or directory

インストール用のディレクトリが内容でしたので下記コマンドで作成し、再度% nodebrew install-binary stableコマンドを実行するとインストールに成功します。

ターミナル
% mkdir -p ~/.nodebrew/src

Node.jsのインストールを確認します。

ターミナル
% nodebrew --version
ターミナル
#上部記述は省略

Example:
    # install
    nodebrew install v8.9.4

    # use a specific version number
    nodebrew use v8.9.4 ←

% nodebrew --versionコマンドで出力された『# use a specific version number』の下部に記載されているコマンドを実行します。するとnot installedと出るのでnodebrew install v8.9.4コマンドを実行し、再度下記コマンドを実行し、not installedと出なければOKです。

ターミナル
% nodebrew use v8.9.4
>use v8.9.4

Node.jsのバージョンが有効化されている事を確認します。
currentに上記と同じバージョンが記載されていれば完了です。

ターミナル
% nodebrew ls

#中略

>current: v8.9.4

下記コマンドでパスを通します。

ターミナル
% echo 'export PATH=$PATH:~/.nodebrew/current/bin/' >> ~/.bashrc

「.bashrc」ファイルがログイン時に読み込まれるように設定していない場合は下記の手順を行います。
「.bash_profile」ファイルを開く

ターミナル
% vi ~/.bash_profile

下記内容を追記し保存します。

ターミナル
source ~/.bashrc

保存後に下記コマンドで「.bashrc」ファイルを読み込みます。

ターミナル
% source ~/.bashrc

パスが通っているか確認します。
command not foundにならなければOKです。
これでNode.jsのインストール完了です。

ターミナル
% npm

次にnpmをインストールします。

ターミナル
% npm install
% npm run dev

下記のようにDONEと表示されれば完了です。

ターミナル
 DONE  Compiled successfully in 5385ms

       Asset     Size   Chunks             Chunk Names
/css/app.css  178 KiB  /js/app  [emitted]  /js/app
  /js/app.js  1.4 MiB  /js/app  [emitted]  /js/app

これでまだ日本語化されていませんが、ログイン機能を実装できています。

日本語化

config.phpファイル内の設定を日本に変更します。

config/app.php 
'timezone' => 'Asia/Tokyo',
#中略
'locale' => 'ja',
#中略
'fallback_locale' => 'ja',
#中略
'faker_locale' => 'ja_JP',

次にインストーラーをダウンロードします。
Laravel 公式が日本語フォルダのインストールを記載してくれているので、利用します。

ターミナル
% php -r "copy('https://readouble.com/laravel/6.x/ja/install-ja-lang-files.php', 'install-ja-lang.php');"

インストーラーを起動します。

ターミナル
% php -f install-ja-lang.php

これでバリデーションエラーなどが日本語化されました。

次にビューの日本語化を行います。
下記のファイルは、% php artisan ui vue --authコマンドを実行した時に生成されたデフォルトのログイン画面のビューファイルです。

resources/views/auth/login.blade.php 
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Login') }}</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('login') }}">
                        @csrf

                        <div class="form-group row">
                            <label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>

                            <div class="col-md-6">
                                <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>

                                @error('email')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

#省略

上記ファイル内に__('Login')という記述があります。
__(  )というい記述は多言語化というもので中の英語を変換し表示することができます。
何も触らない場合はそのままLoginと表示されます。
ちなみにhome.blade.phpやwelcome.blade.phpファイル内にも__(  )を追加して日本語化しています。

次に__(  )の英語を日本語化するため、resources/lang内にja.jsonファイルを作成し、下記の通り記述します。

resources/lang/ja.json 
}
  "Login": "ログイン",
  "Register": "新規登録",
  "Forgot Your Password?": "パスワードを忘れた場合",
  "Reset Password": "パスワード再設定",
  "Send Password Reset Link":  "パスワード再設定URLを送信",

  "Name": "お名前",
  "E-Mail Address": "メールアドレス",
  "Password": "パスワード",
  "Confirm Password": "パスワード(確認用)",
  "Remember Me": "ログイン状態を保存",

  "Hello!": "ご利用ありがとうございます。",
  "Reset Password Notification":  "パスワード再設定のお知らせ",
  "You are receiving this email because we received a password reset request for your account.": "あなたのアカウントでパスワード再発行のリクエストがありました。",
  "This password reset link will expire in :count minutes.": "再設定URLの有効期限は :count 分です。",
  "If you did not request a password reset, no further action is required.": "もしパスワード再発行をリクエストしていない場合、操作は不要です。",
  "If you’re having trouble clicking the \":actionText\" button, copy and paste the URL below\ninto your web browser: [:actionURL](:actionURL)": "\":actionText\"ボタンを押しても何も起きない場合、以下URLをコピーしてWebブラウザに貼り付けてください。\n[:actionURL](:actionURL)",
  "Regards": "よろしくお願いいたします",

  "Home": "マイページ",
  "Logout": "ログアウト",
  "Dashboard": "お知らせ",
  "You are logged in!":"ログインしました!"
}

これでビューに日本語が表示されます。

ユーザー新規登録の編集

usersテーブルへカラムの追加を行います。
今回開発するアプリではデフォルトに所属(belongs)というカラムを追加します。
制約等少々デフォルトから編集しております。
※今回% php artisan migrateを行ったあとに環境設定や日本語化を行っていましたので一度% php artisan migrate:rollbackを行った後に下記ファイルにカラム追加の記述を行います。

resources/lang/ja.json 
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name')->unique();
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->string('belongs'); #これを追加
            $table->timestamps();
        });
    }

そしてmigrateを実行し、カラムを追加します。

ターミナル
% php artisan migrate

Railsのgem deviseではなかった\$table->timestamp('email_verified_at')->nullable();と$table->rememberToken();が気になり、少々調べました。
email_verified_atは、新規登録時にメールが送られ、二段階認証を行うためのもののようです。
ローカル環境でも実験できるのかなどは確認できておらず、動作には問題なかったのでこのまま進めます。
rememberTokenは、ログインを保持するためのもので保持期間がデフォルトでは5年に設定されているそうです。今回はその設定は触らず進めます。このカラムは、このチェックを入れてログインすると保存されるようです。
ログイン画面Qiita-2.png

次にビューファイルに所属情報を入力する欄を追加します。
今回は、デフォルトのパスワード(確認用)の部分をコピペしてlabelタグやinputタグ等のオプションを少々触った程度です。

resources/views/auth/register.php 
#省略

                        <div class="form-group row">
                            <label for="belongs" class="col-md-4 col-form-label text-md-right">所属</label>

                            <div class="col-md-6">
                                <input id="berongs" type="text" class="form-control" name="belongs" required autocomplete="organization" value="{{ old('belongs') }}">

                                @error('belongs')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

#省略

次にコントローラー編集します。
バリデーションを追加します。(必須、文字列、最大文字数255文字となります。)

app/Http/Controllers/Auth/RegisterController.php 
#省略

    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
            'belongs' => ['required', 'string', 'max:255'],  #ここを追加
        ]);
    }

#省略

DBに保存するための記述をします。

app/Http/Controllers/Auth/RegisterController.php 
#省略

    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
            'belongs' => $data['belongs'],  #ここを追加
        ]);
    }

#省略

次にモデル編集します。
$fillableは定義した値しかモデルへ入らないようにするものです。

app/User.php 
#省略

    protected $fillable = [
        'name', 'email', 'password', 'belongs',  #belongsを追加
    ];

#省略

これで新規登録に追加したカラムの入力情報がDBへ保存されるようになります。
ここまで読んで頂きありがとうございます。

参考にさせて頂いた記事

環境設定ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
Laravel6 ログイン機能を実装する @ucan-lab
Mac HomebrewでNode.jsをインストールする @miriwo

Node.jsとはーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
初心者向け!3分で理解するNode.jsとは何か?

日本語化ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
Laravelの言語を日本語に変更qiita @mitashun
Laravel の言語を日本語に変更
ログイン認証機能の日本語化(laravel6)

vue.jsの使い方ーーーーーーーーーーーーーーーーーーーーーーーーーーーー
合わせてvue.jsについて調べた際に今後参考になりそうだと思い、閲覧させて頂いた記事をご紹介させて頂きます。
Vue.jsでjQueryと共存させる方法 @g-taguchi
jQuery から Vue.js へのステップアップ @mio3io
1週間でVue.jsをマスターしようと思った時に参考にしたサイト @mimoe

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

HerokuにLaravelで作ったアプリをデプロイする方法(MySQL編)

Laravel 7.16.1でTwitterっぽいSNSツールを作る」で作成したアプリをHerokuでデプロイする方法をご紹介します。
以前はPostgreSQLを使う手順をご紹介しましたが、今回はデータベースはMySQLを使って構築します。

参考ページ

Laravelをherokuにデプロイする(データベースはMySQL)
Laravel 6.x on Heroku mailgun アドオンでメール送信実装手順

作業環境

OS:Windows 10 HOMEエディション (ver.2004)
Laravel:ver.7.16.1
Composer:ver.1.10.7
Git:ver.2.26.2.windows.1

前提条件

・既にLaravelでアプリの公開する準備が終わっていること
・Herokuでアカウントの登録が済んでいること

Heroku に新規アプリを作成する

以下のコマンドを実行します。

cd 'アプリのあるフォルダ'
heroku login
heroku create twitter-laravel-neneta
 --buildpack heroku/php

「twitter-laravel-neneta」はアプリ名ですが、他の人と同じ名前をつけることができないので注意です。名前にこだわりがなければ「heroku create」だけでもOKです。

DBを設定する

「ClearDB MySQL」を追加

DBはMySQLを利用するので、「ClearDB MySQL」を追加します。プランが「Ignite - Free」になっているのかどうかを確認してください。
202006211029.png

DBの接続情報を設定する

下記のコマンドを入力すると、DBの接続情報をが表示されます。

heroku config:get CLEARDB_DATABASE_URL

CLEARDB_DATABASE_URLで表される接続 URL は以下の形式になっています。

mysql://aaaaa:bbbbb@ccccc/ddddd?reconnect=true
mysql://[ユーザー名]:[パスワード]@[ホスト名]/[データベース名]?reconnect=true

それぞれ config:set コマンドで設定します。DB_CONNECTION は mysql に設定します。

heroku config:set DB_CONNECTION=mysql
heroku config:set DB_HOST=ccccc
heroku config:set DB_DATABASE=ddddd
heroku config:set DB_USERNAME=aaaaa
heroku config:set DB_PASSWORD=bbbbb

以上でDBの設定は終了です。

メールサーバーを設定する

「ClearDB MySQL」と同じ要領で、今度はメールサーバーを用意します。今回は「
Mailgun」を利用します。こちらも無料プランがありますので、「Starter - Free」を選びます。
202006211050.png

メールアドレスの認証

「Mailgun」を追加できたら、受信するメールアドレスの認証を行います。以下のコマンドでmailgunのダッシュボードを表示します。

heroku addons:open mailgun

左のメニューから[Sending] > [Domains]を開き、デフォルトで作成されているSandboxドメインをクリックして開きます。
202006211059.png
下にある[Authorized Recipients]の[Email address]に受信者のメールアドレスを入力して[Save Recipient]をクリックします。
202006211103.png
以下のように[Unverified]の状態で追加されます。
202006211104.png
入力したメールアドレス宛に「Would you like to receive emails from Heroku Account on Mailgun?」というタイトルのメールが送信されるので[I Agree]をクリックします。
202006211106.png
Confirm画面が表示されるので[Yes]をクリックします。
202006211107.png
Successと表示されるとメールが受信できるようになります。
202006211108.png
先程の画面に戻り更新すると、以下のように[Verified]の状態に変更されます。
202006211109.png

メールサーバーの接続情報を設定する

下記のコマンドを入力して、メールサーバーの設定を行います。

heroku config:set MAIL_DRIVER=mailgun
heroku config:set MAILGUN_DOMAIN="heroku config:get MAILGUN_DOMAIN"
heroku config:set MAILGUN_SECRET="heroku config:get MAILGUN_API_KEY"

以上でメールサーバーの設定は終了です。

デプロイ

Procfileを作成する

まず Procfile という Heroku 向けの設定ファイルを作成します。
エディタで「Procfile」というファイル名のファイルを作成し、以下の内容を記述して保存します。

Procfile
web: vendor/bin/heroku-php-apache2 public/

アップロード

Heroku へのアップロードは Git を利用します。
先にアプリケーションコードを Git の管理下に置いてから、heroku create したときに設定された heroku リモートリポジトリにプッシュすると自動的にそのコードがアプリケーション実行環境にも送信され、配置されます。
以下のコマンドを順に実行します。

git init
git add .
git commit -m "first commit"
git push heroku master

下記のようなエラーが出ました。
202006211146.png
「composer.json」を下記のように修正しました。

composer.json
変更前
"prefer-stable": true,
"scripts": {
        "post-autoload-dump": [
            "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
            "@php artisan package:discover --ansi"
        ],
        "post-root-package-install": [
            "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
        ],
        "post-create-project-cmd": [
            "@php artisan key:generate --ansi"
        ]
}

変更後
"prefer-stable": true

APP_KEY

アプリケーションをアップロードできたら、まずは APP_KEY の設定を行います。セキュリティ関連の機能で暗号化に使ったりと重要な設定項目で、これがないと Laravel は動作しません。

heroku config:set APP_KEY="php artisan --no-ansi key:generate --show"

マイグレーション

データベースの状態はマイグレーションファイルで管理しているので、本番公開のときもマイグレーションコマンドでテーブルが構築できます。

heroku run "php artisan migrate"

Do you really wish to run this command? (yes/no) [no]:

途中で本当に実行していいかどうか確認が出てくるので、「yes」と入力するとテーブルが作成されます。

ここでも下記のようなエラーが出ました。
202006211154.png
「laravel/ui package」がインストールされていないみたいなので、再度「composer.json」を下記のように修正しました。

composer.json
変更前
"require": {
        "php": "^7.2.5",
        "barryvdh/laravel-debugbar": "^3.3",
        "fideloper/proxy": "^4.2",
        "fruitcake/laravel-cors": "^1.0",
        "guzzlehttp/guzzle": "^6.5",
        "laravel/framework": "^7.0",
        "laravel/tinker": "^2.0"
},

変更後
"require": {
        "php": "^7.2.5",
        "barryvdh/laravel-debugbar": "^3.3",
        "fideloper/proxy": "^4.2",
        "fruitcake/laravel-cors": "^1.0",
        "guzzlehttp/guzzle": "^6.5",
        "laravel/framework": "^7.0",
        "laravel/tinker": "^2.0",
        "laravel/ui": "^2.0"
},

「composer.json」を編集した後は、下記のコマンドも実行します。

composer dump-autoload

再度git push heroku masterを実行したところ、違うエラーが出ました。
202006211202.png
「laravel/ui package」がインストールされていないみたいなので、エラーに書いてある通りにコマンドを実行します。

composer update
git add composer.json composer.lock
git commit -m "fixed error"

再度heroku run "php artisan migrate"を実行し、完了しました。

ブラウザで開く

以下のコマンドを入力し、ブラウザから開きます。

heroku open

アプリケーションを更新したときは、以下のコマンドで更新できます。

git add .
git commit -m "コミットメッセージ"
git push heroku master

エラーが出てきました。
202006211215.png
とりあえず、以下のコマンドを実行してみました。

heroku config:set APP_ENV=heroku
heroku config:set LANG=ja
heroku config:set TZ=Asia/Tokyo

何も変化はありませんが、よく見るとAPP_KEYがうまく設定されていませんでした。PowerShellを管理者権限で起動して下記のコマンドを実行すると治りました。(まだところどころエラーが起きてますが・・・)

heroku config:set APP_KEY=$(php artisan --no-ansi key:generate --show)

参考までに今回公開したアプリはこちらです。
https://twitter-laravel-neneta.herokuapp.com/

以上、簡単ですがHerokuにアプリをデプロイする手順をご紹介しました。

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

YoutubeAPI $ composer require google/apiclient:~2.0で詰まった件について

初投稿になります。
見辛い記事かと思いますがご容赦ください。。

今回、オリジナルポートフォリオを作るにあたって、LaravelからYoutubeAPIを使い動画のアップロードをしたいと考えました。
その際そもそものインストールや認証などでかなり詰まったので備忘録として記事にしておきたいと思った次第です。

環境
AWS EC2 Micro無料枠
Docker Laradockにて構築
PHP7.3
Laravel 6.10.0

まずは公式からサンプルコードをコピーしてきました。
https://developers.google.com/youtube/v3/code_samples/php?hl=ja#resumable_uploads

レジューム可能なアップロード
次のコード サンプルは API の videos.insert メソッドを呼び出して、ユーザーのチャンネルに動画を追加します。また、このコードは Google_MediaFileUpload クラスに true に設定した resumable upload パラメータを付けて使用して、動画を分割してアップロードできるようにしています。

<コードは長いので割愛>

詰まりポイント① composerがUpdateできない。
原因:AWS無料枠のメモリ不足

まずは$ composer require google/apiclient:~2.0をインストールしろと言われるのですが、そのためにはComposerをUpdateする必要があるらしいので、$ composer update を実行すると、下記エラーが出ました。
mmap() failed: [12] Cannot allocate memory

https://tsukada.sumito.jp/2019/11/26/mmap-failed-12-cannot-allocate-memory/
こちらの方法でswapすることで無事解決。
今回は2048GB回しました。
(ちなみにどうやら保存領域から削ってメモリに充てているっぽい?ので、やりすぎると次はInstall容量を確保できなくなる疑惑。。)

これでComposerがUpdateできました。

詰まりポイント② $ composer require google/apiclient:~2.0が実行できない。
原因:composer.json上でリクエストしているバージョンが誤っていた。

満を辞して
$ composer require google/apiclient:~2.0を実行すると、

./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

Problem 1
- The requested package laravel/framework (locked at v6.10.1, required as ^6.18) is satisfiable by laravel/framework[v6.10.1] but these conflict with your requirements or minimum-stability.
Problem 2
- Conclusion: don't install laravel/framework v6.18.19
- Conclusion: don't install laravel/framework v6.18.18
- Conclusion: don't install laravel/framework v6.18.17
- Conclusion: don't install laravel/framework v6.18.16
- Conclusion: don't install laravel/framework v6.18.15
- Conclusion: don't install laravel/framework v6.18.14
- Conclusion: don't install laravel/framework v6.18.13
- Conclusion: don't install laravel/framework v6.18.12

〜〜〜〜〜〜
〜〜〜〜〜〜
〜〜〜〜〜〜

  • Installation request for laravel/framework ^6.18 -> satisfiable by laravel/framework[6.x-dev, v6.18.0, v6.18.1, v6.18.10, v6.18.11, v6.18.12, v6.18.13, v6.18.14, v6.18.15, v6.18.16, v6.18.17, v6.18.18, v6.18.19, v6.18.2, v6.18.3, v6.18.4, v6.18.5, v6.18.6, v6.18.7, v6.18.8, v6.18.9].
  • Installation request for laravelcollective/html ~5.0 -> satisfiable by laravelcollective/html[5.0.x-dev, 5.1.x-dev, 5.2.x-dev, 5.3.x-dev, 5.4.x-dev, 5.5.x-dev, 5.6.x-dev, 5.7.x-dev, 5.8.x-dev, v5.0.0, v5.0.1, v5.0.2, v5.0.3, v5.0.4, v5.0.5, v5.1.0, v5.1.1, v5.1.10, v5.1.11, v5.1.2, v5.1.3, v5.1.4, v5.1.5, v5.1.6, v5.1.7, v5.1.8, v5.1.9, v5.2, v5.2.1, v5.2.2, v5.2.3, v5.2.4, v5.2.5, v5.2.6, v5.3.0, v5.3.1, v5.3.2, v5.4, v5.4.1, v5.4.2, v5.4.3, v5.4.4, v5.4.5, v5.4.6, v5.4.7, v5.4.8, v5.4.9, v5.5, v5.5.1, v5.5.2, v5.5.3, v5.5.4, v5.6, v5.6.1, v5.6.10, v5.6.2, v5.6.3, v5.6.4, v5.6.5, v5.6.6, v5.6.7, v5.6.8, v5.6.9, v5.7, v5.7.1, v5.8.0, v5.8.1].

ズラーっとエラーが吐き出されます。。

問題は2つあって、composer.json上で、
・laravel/frameworkが現在6.10.1なのに、6.18というバージョンをリクエストしていた。
.laravelcollective/htmlを5.0以下でリクエストしているが、安定稼働?なのはこのバージョンじゃなかった。

となり、以下のように修正をすることでインストールが完了しました。

(composer.json)

"require": {
"php": "^7.2",
"aws/aws-sdk-php": "^3.133",
"fideloper/proxy": "^4.0",
"google/apiclient": "~2.0",
"guzzlehttp/guzzle": "^6.5",
"laravel/framework": "^6.10.1",
"laravel/helpers": "^1.1",
"laravel/tinker": "^2.0",
"laravel/ui": "^1.1",
"laravelcollective/html": "~6.0"
},

この記事を書いている段階ではまだYoutubeAPIが使えていないのですが、
一応備忘録として。。またできたら更新します。

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

【Laravel】{!! $html !!}をする時のハマりどころと要点

最近、 DBに保存されているフォーム(HTMLコード)と、これまたDBに保存したユーザーの回答データを画面上に表示する、という機能に触ることがありました。

その時にHTMLエンティティ変換の煩わしさとXSSの沼にハマったので、配慮するべきポイントについてまとめておきます。

{!! $html !!}について

form.blade.php
// $html = '<p>XSS</p>'

// 
{!! $html !!}

// $xss = "<script>alert('かかったな!');</script>";
{!! $xss !!}

↑のようにすることで展開した変数が文字ではなくコードとして意味を持ち得るコードになる。
``
DBから取得し、変数に格納したHTMLコード

この辺りは公式:エスケープしないデータの表示

①HTMLエスケープはhtmlspecialchars($value, ENT_QUOTES, 'UTF-8', $doubleEncode)

htmlspecialcharsENT_QUOTESを付けないとシングルクォート ` をエスケープしてくれません。

$no_escape = htmlspecialchars($single_quote);
echo $no_escape;
// ' と表示


$escaped = htmlspecialchars($input, ENT_QUOTES, 'UTF-8');
echo $escape;
// &#039; と表示(HTML上では ` で表示)

HTMLでは値の区切りに"を使うのがセオリーなのですが、シングルクォートも使えます。

<?php $xss = '\'/><script>alert(\'XSS\');</script>'; ?>
<input type="text" value='<?php echo $xss; ?>'>

誰かがうっかりシングルクォートを使ったフォームを作成してしまってもいいように、ENT_QUOTESは忘れずに付けましょう。

Laravelのe()を使うor参考にする

Laravelを使っているならヘルパ関数e()を使えばこの辺りに配慮した対応をしてくれます。
使ってない方でも、e()の中身を参考にHTMLエスケープするといいでしょう。

/Illuminate/Support/helpers.php
if (! function_exists('e')) {
    /**
     * Encode HTML special characters in a string.
     *
     * @param  \Illuminate\Contracts\Support\Htmlable|string  $value
     * @param  bool  $doubleEncode
     * @return string
     */
    function e($value, $doubleEncode = true)
    {
        if ($value instanceof Htmlable) {
            return $value->toHtml();
        }

        return htmlspecialchars($value, ENT_QUOTES, 'UTF-8', $doubleEncode);
    }
}

ちなみに、第3引数のエンコーディング規格を指定しない場合、各バージョンのPHPによって自動的に規格が適用されます。

公式では明示的に指定することを推奨しています。

②htmlentities()は基本、使わない

htmlentities()も文字列をHTMLエンティティにしてくれますが、コードとしての意味を持たない(XSSリスクに関係ない)文字列まで変換します。

参考:PHPのhtmlentities()とhtmlspecialchars()の違いと適切なエンティティ変換

NGではないですが、オーバースペックな関数です。
htmlspecialchars()とデコードのための関数が異なる=デコード間違いによるバグのリスクを生む可能性があるため、特別な理由がない限りは使わないでいいでしょう。

③適切なデコード関数を使うはhtmlspecialchar_decode()を使う

htmlspecialchars($value, ENT_QUOTES, 'UTF-8', $doubleEncode);
でデコードした文字列はhtmlspecialchar_decode()を使ってデコードしましょう。ENT_QUOTEを忘れずに!
php
htmlspecialchar_decode($str, ENT_QUOTE);

②のhtmlentities()を使った文字列に対してはhtml_entity_decodeを使います。

html_entity_decode($str, ENT_QUOTE);

④DBに保存する情報はそのままでOK

'><script>alert('XSS');</script>みたいな入力がされたからといって、それが即有害な文字列だとはいい切れません。

DBにvarchar型で保存されたり、CSVファイルに出力される分には実害はありません。情報はHTMLにレンダリングされるとは限らないのです。

XSSに用いられるような文字列表現が無条件に有害とはいえない、といえます。
(その意味で、サニタイズ(消毒)という言葉は不適切であり、セキュリティワードに繊細な方からは敬遠されているんだとか)

仮にDBから引っ張ってきたエスケープ文字列をvue.jsのdata()に入れて表示させると、エスケープされたままの文字列が表示されてしまいます。

文字列をエスケープした状態でDBに保存したりすると、HTML以外に出力する時全てのケースでデコードしなければならないので、対応コストが爆増します。

DBに保存する情報はそのままでOK、必要に応じてエンコード処理を加えるという考えでいきましょう。

⑤inputのvalueに入る値にもHTMLエンティティは有効になる

<input type="text" value="&amp; ">
// input内に & に変換、表示される

valueに入る時もHTMLエンティティは文字列に変換されます。

初歩的なことかもしれませんが、考えすぎてエスケープ処理がゲシュタルト崩壊してくると判断が付かなくなったので、備忘録として。

参考資料

サニタイズ/入力値検証/エスケープの考え方
IPA 安全なウェブサイトの作り方
悪いサニタイズ、そして良い(?)サニタイズ、そして例外処理
PHPのhtmlentities()とhtmlspecialchars()の違いと適切なエンティティ変換

まとめ

調べれば調べるほど{!! $html !!}を使うこと自体がアンチパターンじゃないの?と思えてきますね。

とはいえ、普段FWがよしなにやってくれている部分を勉強するいい機会になりました。

参考にさせていただいた資料はとてもよくまとまっているので、併せて参照していただければと思います!

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

【Laravel】例外処理(try...catch)でのデバッグ

はじめに

例外を発生させたい時、try...catch文を使うかと思います。
その時のデバッグ方法についてメモです。

これまで

test.php
try {
// 略 
} catch (\Exception $e) {
    $e-getMessage();
    session()->flash('flash_message', '更新が失敗しました');
}

というような感じでgetMessageメソッドで使っておりました。
これだとエラーの原因(ex:undefined $hoge)は分かるのですが、どの行でエラーを起こしているかという情報までは出力されないんですよね。。。

というわけで、、、

こうしました

test.php
try {
// 略 
} catch (\Exception $e) {
    report($e);
    session()->flash('flash_message', '更新が失敗しました');
}

reportメソッドを使うと、どのファイルの何行目で処理が止まっているか(エラーが起きているか)まで出力してくれます。

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