20200315のlaravelに関する記事は8件です。

Send Mail from laravel using SMTP on XSERVER

Environment

MAIL_DRIVER=smtp   
MAIL_HOST=sv[YOUR_NUM].xserver.jp           
MAIL_PORT=587
MAIL_USERNAME=[YOUR_MAIL]
MAIL_PASSWORD=[PASSWORD_FOR_YOUR_MAIL]
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=[ADDRESS_YOU_WANT]
MAIL_FROM_NAME=[ANYTHING_YOU_WANT]

※Domain name of MAIL_FROM_ADDRESS have to be same as MAIL_HOST.

Controller

<?php                                                                                                                                                                                                                                     

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Mail;

class SendmailController extends Controller
{
    public function sendMail() 
    {   
        Mail::send('mail', array(), function($message){
            $message->to('address@example.com', 'Title')->subject('Test mail');
        }); 
    }   
}

SPF Record

If you can't send mail from xserver, please check your spf record on xserver.

CAUTION

If you put your server without Japan.
You need to change setting like below.

Artboard.png

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

【Laravel】 外部制約キーを migration で設定しようとしたらエラー

何が起きたか

hoge テーブルに users テーブルのid で外部制約キーを設定しようと migrate 実行時にエラーが

結論

bigIntegerで制約を付けたいカラムにを定義しないと、 migrationファイル作成時に記述されている $table->id() と型が異なってしまう

知っていればつまづくポイントにもならないと思いますが、自分の備忘録として・・・

エラーパターン

migration

// users テーブル

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('login_id');
        $table->string('password');
        $table->timestamps();
    });
}
// hoge テーブル

public function up()
{
    Schema::create('hoge', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->integer('user_id')->unsigned();
        $table->timestamps();
        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
    });
}

エラー内容

エラーを見ると
Cannot add foreign key constraint

...エラーが起きたのどこだろ

MySqlの場合下記実行でエラー内容の詳細が見れる。

SHOW ENGINE INNODB STATUS;

status カラムの LATEST FOREIGN KEY ERROR とある部分を見ると

Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.

エラーに従って usersidhogeuser_id をチェックすると
users.idBIGINT
hoge.user_idINT

型が違った

修正内容

hoge テーブルの user_id 定義を変更してやればOK

// hoge テーブル 修正後

public function up()
{
    Schema::create('hoge', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->bigInteger('user_id')->unsigned();
        $table->timestamps();
        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
    });
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Google認証(ManagementAPI利用時)にて「idpiframe_initialization_failed 」エラー

Google Management APIを使うために、JavaScriptのクイックスタート「HelloAnalytics.html」では普通に取得に成功。

しかし、Laravelに移管して試すと、なぜかresponse.errorで「idpiframe_initialization_failed 」が帰ってくる。

調べるとcookieとかなんとか書いてある記事ばかりにぶつかるが、ブラウザ設定の問題であれば、なぜHelloAnalyticsではうまくいくのか問題があるので、調べていると「response.details」で詳細も調べられる模様。

すると、「Not a valid origin for the client: http://localhost:8000 has not been whitelisted for client ID 445466545626-no2p05n4ehh5f2q8ria3loh78ddh6r1k.apps.googleusercontent.com. Please go to https://console.developers.google.com/ and whitelist this origin for your project's client ID.」と、要はDeveloper Consoleでホワイトリストに入れていないからダメというアラート。

いやいや、localhostはきちんと入力しているし、クイックスタートもlocalhostだけど動いてるやん!

https://stackoverflow.com/questions/43964539/google-api-not-a-valid-origin-for-the-client-url-has-not-been-whitelisted-for

この記事で解決。

どうも、Google認証の「OAuth 2.0 クライアント ID」は、一度あるポートで使うと、その後で違うポートで利用することはできないらしい。

クイックスタートはMAMP(ポート80)で動かしていて、LaravelはLaravelサーバ(ポート8000)で動かしたためNGだった模様。

新しくOAuth 2.0 クライアント IDを作り直したら、あっさり解決。

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

laravelの学習のためにECサイトを作成した

トップページ

FireShot Capture 009 - LaraEC - localhost.png
トップページはバナーと商品一覧を表示しています。
ページネーションはlaravelのlinksメソッドを使用しています。

{{ $stocks->links() }} 

カートページ

FireShot Capture 011 - LaraEC - localhost.png
カートに入れた商品の個数と合計金額が表示されるようになっています。

購入完了ページ

FireShot Capture 012 - LaraEC - localhost.png
「購入する」ボタンを押すと確認ページに移動して、カートの中身がすべて削除されます。

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

Laravelでかんたんな日記を作る

完全に自分の学習日記ですが、チュートリアル的なものになればいいなあ、ということで随時まとめます。

環境構築

最新のlaravel7を用います。
ここではwindows 10 pro+vscode+laradockでの開発を想定しています。
そのへんのややこしいところは他の記事を参照してください。

各自laradockをクローンして、docker-compose up -d nginx mysqlを実行し、composer laravel/laravel hogehogeしてください。

テンプレートの作成

【Laravel】Viewのbladeの書き方 をベースに(そのまま丸パクリ)してるので割愛。

データベース・テーブルの作成

日記なので記事を保存しなければなりません。そのためにかんたんなDBを作成します。
今回はこんな感じの1つのテーブルがあれば良いでしょう。
articlesテーブル

id タイトル 本文 投稿日 投稿者 編集日 編集者
id title content create_at created_by update_at update_by
bigint char(128) text timestamp tinyint(4) timestamp tinyint(4)

ここで投稿者と編集者をtinyintにしているのは、今後会員機能を追加するためです。今回は割愛。

mysqlに接続し、データベースを作成します。DB名は標準のlaravelとします。

やり方は割愛。

マイグレーションファイルの作成

$ artisan make:migration articles
Created Migration: 2020_03_15_090146_articles

中身を以下のように編集します。

2020_03_15_090146_articles.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class Articles extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('articles', function(Blueprint $table){
            $table->id();
            $table->char('title', 128);
            $table->text('content');
            $table->timestamps();
            $table->tinyInteger('created_by');
            $table->tinyInteger('update_by');


        })
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('articles');
    }
}

マイグレーションを実行します。

$ artisan migrate
Migrating: 2020_03_15_090146_articles
Migrated:  2020_03_15_090146_articles (0.04 seconds)

テーブルが作成されたことを確認します。
image.png

投稿画面の作成

日記を投稿する画面を作ります。

Eloquentモデルの作成

ここではORMを利用します。まずArticleモデルを作ります。
ORMについては私の記事を参考にしてください。

$ artisan make:model Article
Model created successfully.

Articleモデルを以下のように編集します。

Article.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Article extends Model
{
    protected $table = 'articles';
    // ユーザー系は作っていないのでデフォルト値を指定する
    protected $attributes = [
        'created_by' => 0,
        'update_by' => 0,
    ];
}


投稿画面の作成

new_article.blade.phpを作成します。今回は投稿さえできればいいのでデザインは考慮しません。

@extends('layouts.app')

@section('title','記事の作成')

@section('content')
<div class="content">
<form method="post">
    @csrf
    <label>タイトル: <input id="title" type="text" name="title" value=""></label>
    <label>本文: <input id="content" type="text" name="content" value=""></label>
    <input type="submit" name="submit" value="投稿する">
</form>
</div>

@endsection

ちなみにlayouts.appは丸パクリしたものなので割愛します。

では、次に投稿の処理を行うコントローラークラスを作成します。

$ artisan make:controller PostController
Controller created successfully.

編集します。

PostController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Article;

class PostController extends Controller
{
    public function create(Request $request){
        $article = new Article();

        $article->title = $request->title;
        $article->content = $request->content;

        $article->save();
        return redirect('/'); //とりあえずトップページに戻る。
    }
}

ルーティングの設定

ルーティングの設定をしてDBに保存させます。

web.php
<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('index');
});

Route::get('/create', function () {
    return view('new_article');
});

Route::post('/create', 'PostController@create');

投稿結果を表示させる

日記なので読めなければ意味がありません。
ここではとりあえずindexに一覧表示させるようにします。
コントローラークラスを作成します。

$ artisan make:controller GetController
Controller created successfully.

編集します。

GetController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Article;

class GetController extends Controller
{
    public function read(){
        $articles = Article::all();

        return view('index', ['Articles' => $articles]);
    }
}

ルーティングの設定

以下のように書き換えます。

web.php
<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('index');
});

Route::get('/', 'GetController@read');

Route::get('/create', function(){
    return view('new_article');
});

Route::post('/create', 'PostController@create');

bladeの編集

ようやく最後です。bladeを編集します。

index.blade.php
@extends('layouts.app')

@section('title', 'laravel日記')

@section('content')
    <div class="link"><a href='/create'>新規投稿<a></div>
    <div class="content">投稿内容</div>
    @foreach($articles as $article)
    <p>

    投稿番号:{{$article->id}} /<b>{{$article->title}}</b><br>
    {{$article->content}}<br>
    投稿日:{{$article->created_at}}
    </p>
    @endforeach
@endsection

これでとりあえず動きました。

まとめ

とりあえず動く掲示板のような日記のようなものは完成。
今後はデザインの方に力を入れたり、ログイン機能を作ります。

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

商用環境でも使っている Laravel 用 php-fpm イメージの Dockerfile レシピ

これは何

Laravel 用 php-fpm イメージの Dockerfile。
(多少はフォーマット変わろうとも)色んなところでずっと使いまわししそうなのでメモ。

完全に個人の秘伝のタレ化するよりは情報公開したほうが自社にとっても利益があるだろうと判断(笑)
異論は無限に受け付けるので改善点などあればコメントください。

レシピ

FROM golang:1.13 as HTTP2FCGI_BUILD

# http2fcgi のビルド
RUN apt update -y \
 && go get -v -ldflags '-w -s' github.com/alash3al/http2fcgi/...

FROM php:7.4-fpm-alpine

# Goバイナリが実行できるようにする
# https://stackoverflow.com/questions/34729748/installed-go-binary-not-found-in-path-on-alpine-linux-docker
RUN mkdir /lib64 \
 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2

# http2fcgi のインストール
COPY --from=HTTP2FCGI_BUILD /go/bin/http2fcgi /bin/http2fcgi

# Git のインストール
RUN apk add --update --no-cache git

# Composer のインストール
RUN set -eux \
 && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
 && composer global require hirak/prestissimo \
 && composer config -g repos.packagist composer https://packagist.jp

# PHP 拡張のインストール
RUN set -eux \
 && apk add --update --no-cache autoconf g++ libtool make libzip-dev libpng-dev libjpeg-turbo-dev freetype-dev \
 && pecl install redis \
 && docker-php-ext-configure gd --with-jpeg=/usr \
 && docker-php-ext-configure opcache --enable-opcache \
 && docker-php-ext-install opcache bcmath pdo_mysql gd exif zip \
 && docker-php-ext-enable redis \
 && apk del autoconf g++ libtool make \
 && rm -rf /tmp/*

# ビルド引数
ARG DEPLOY
ARG PHP_COVERAGE_DRIVER=""

# カバレッジ計測およびデバッグ用 PHP 拡張のインストール
#  - ローカルでは xdebug を入れる
#  - CI では pcov を入れる
#  - プロダクションでは何も入れない
RUN set -eux \
 && apk add --update --no-cache autoconf g++ libtool make \
 && if [ "$DEPLOY" = "local" -a "$PHP_COVERAGE_DRIVER" = "pcov" ]; then \
      pecl install pcov; \
      docker-php-ext-enable pcov; \
      echo "pcov.directory = /code/app" >> $PHP_INI_DIR/conf.d/docker-php-ext-pcov.ini; \
    elif [ "$DEPLOY" = "local" ]; then \
      pecl install xdebug; \
      docker-php-ext-enable xdebug; \
    fi \
 && apk del autoconf g++ libtool make \
 && rm -rf /tmp/*

# php.ini のコピー(ビルド引数によって分岐)
COPY docker/php-fpm/conf.d/$DEPLOY.ini /usr/local/etc/php/conf.d/custom.ini

# Composer 依存パッケージ定義のコピー
COPY composer.json /code/composer.json
COPY composer.lock /code/composer.lock

# Composer 依存パッケージをアプリケーションから分離して先にインストール(ビルド時間短縮のため)
ARG GITHUB_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
RUN set -eux \
 && mkdir -p ~/.composer \
 && printf '{"github-oauth":{"github.com":"%s"}}' $GITHUB_TOKEN > ~/.composer/auth.json \
 && cd /code \
 && composer install --no-scripts --no-autoloader \
 && rm ~/.composer/auth.json

# アプリケーションのコードをコピー(.dockerignore で vendor や .git は除外されている)
COPY . /code

# オートロードファイルの生成
# (ローカルではキャッシュを生成しない)
RUN set -eux \
 && cd /code \
 && composer dump-autoload -o \
 && if [ "$DEPLOY" != "local" ] ; then \
      php artisan config:cache; \
      php artisan route:cache; \
    fi \
 && chown -R www-data:www-data storage

USER www-data
WORKDIR /code

# php-fpm と http2fcgi を起動
# (プリロードを導入したら opcache:compile は消す)
CMD ["sh", "-c", "\
    { \
        sleep 5 && \
        http2fcgi --fcgi tcp://localhost:9000 \
                  --http localhost:8000 \
                  --root /code/public & \
        sleep 10 && \
        ./artisan opcache:compile & \
    } & \
    exec php-fpm"]

ポイント

  • ビルド引数としてデプロイ先環境を表す DEPLOY が必要。ローカルおよび CI のテスト実行用ビルドでは local を指定する。
  • ビルド高速化のため,パッケージインストールは composer.json composer.lock に変更があった場合にしか走らないように工夫している。
    1. composer.jsoncomposer.lock をコンテナ内にコピー
    2. composer install --no-scripts --no-autoloader で,スクリプト実行無しおよびオートローダ作成無しにして, vendor ディレクトリへのファイル投入だけを目的として実行。
    3. アプリケーションのコードをマウント。この際 vendor ディレクトリは除外されている。
    4. composer dump-autoload -o で後からオートローダを作成。
  • パッケージインストール高速化のため, Composer の並列インストールプラグイン hirak/prestissimo および日本国内ミラー Packagist.JP を使用している。
    • 但し, Circle CI などでのビルドを考慮する場合はミラーではなく本家を参照したほうがいいかもしれない。ARG で分岐の余地あり。
  • GitHub のプライベートリポジトリからパッケージをインストールできるように, 会社の共用アカウントで発行したこの目的専用の GITHUB_TOKENARG のデフォルト値としてハードコーディング。
  • エクステンションとして,さまざまな PHP アプリケーションで頻繁に必要になりそうな opcache bcmath pdo_mysql gd exif zip あたりをカバー。必要に応じて追加と削除の余地あり。
  • カバレッジドライバとして krakjoe/pcov を採用。 CI の高速化のため, xdebug はローカルのみインストール対象にし, CI では pcov でカバレッジを取るようにしている。
  • OPCache のコントロールユーティリティ appstract/laravel-opcache および Golang 製の軽量 FastCGI リバースプロキシ alash3al/http2fcgi を採用。
    • PHP 7.4 のプリロード対応が入った後は不要になるが,現状 Laravel ではまともに動かない。
    • 起動時にキャッシュを温めている。但し若干 php-fpm が準備完了状態になるまで時間差があるため,適当な時間 sleep を入れている。
    • Golang バイナリのビルドのためにマルチステージビルドを使用している。

その他注意点

  • DEPLOY はあくまでビルド用に存在する環境変数であり,コンテナ実行時には存在しない。ところがビルド時に config:cache を呼ぶタイミングでは存在しているため,設定ファイルに env('DEPLOY') とか書いてしまうとそれが拾われてキャッシュされてしまい,キャッシュしないと動かないという歪んだ状態に陥ってしまうので注意する。この変数はアプリケーションからは参照してはいけない。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【MacOS】Laravelの環境構築 ~公式サイトコピペでうまくできんかった~

きっかけ

普段はフロントエンドを勉強しているのですが、
ど深夜に急に
「Laravelやってみたい」
と思い公式サイトとcomposerで環境づくりしてました。
そして見事にハマり、時間取られた...

その後、どうやって解消したのかをサクッと紹介したいと思います。
超シンプルに書きます。

環境

macOS Mojave
10.14.6

やりかた

Homebrew → Composer → Laravel
の順でインストールしていきます!

Homebrew

↓まずはHomebrewのサイトでインストールのスクリプト部分をコピーします。
https://brew.sh/index_ja

執筆時のスクリプト.
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

これをターミナルで実行。

途中でエンター押すように促されるので、押しましょう。
しばらく待機し、完了したらHomeBrewインストール終了。

composer

先ほどインストールしたHomebrewを使ってインストールします。
以下コマンドを実行。

ターミナル.
brew install homebrew/core/composer

これもしばらく待機し、完了したらcomposeインストール完了。

試しにターミナルで「composer」と打ち込んで

kitaken$ composer
   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/

と出れば成功。(実行した後、ターミナルで上に戻るとあります。)

Laravel

最後にcomposerでLaravelをインストールします!
Laravelを構築したいファイル下に移動した後、

composer create-project --prefer-dist laravel/laravel プロジェクト名

でLaravelの基盤が作れる。
プロジェクト名は何でもOK。
今回「MyLaravel」とすると

ターミナル.
composer create-project --prefer-dist laravel/laravel MyLaravel

を実行し、しばらく待つと最後に「Application key set successfully.」
と出れば成功です!

プロジェクト作りたいときは、毎回このコマンドを使います!

なぜできなかったのか

Homebrewを使わないやり方をしようとしていた...?
使わないやり方が上手くできませんでした...

そして最初からやり直したことで、うまくいきました。

もしそれでもできないという方は、やり直してみたり、下記参考記事をみてみてください。
参考記事
https://tektektech.com/laravel-make-environment/22/

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

Laravel7にアップグレードすると、artisanコマンドが死ぬ

Laravel7がでましたね!早速人柱的に上げてみましたところ、案の定動かなくなりました。
Laravel6からLaravel7へアップグレードすると、artisanコマンドが謎のステータスコード255を吐いて死にます。
これはcomposer updateしたときに

Script @php artisan package:discover handling the post-autoload-dump event returned with error code 255

なエラーとなって表れてきます。
ググってもやれcacheを消せだの出てきますが、全く効果がありません!!
この時には、

php artisan --version

と叩いてもコンソールに何も出てこなくて、

echo $?
255

っとでるので、artisanコマンド自体が死んでいることが分かります。
これ、とてもとても地味にハマって数時間悩んだのですが、
アップグレードガイドのSymfony 5 Related Upgrades
が該当します。(といってもさらっと流しただけだと気づかないんですが)
修正方法はこれです。

app/Exceptions/Handler.php が今回修正対象となっていまして、 最初にこれを上記のように修正しないとartisanコマンドが動作しません。
なおこれは、

composer update --vvv

として詳細ログをみても、php.iniのエラーレベルをE_ALLにしても何も出てきません。artisanコマンド中のkernel->handler()で音もなく死にます・・・


余談ですが、Laravel7にすると、npmみたいにphp artisan test でテストが実行できます。

./vender/bin/phpunit

とかしなくてもいいです。
見やすく整形されていい感じですよ。

root@03791d802551:/var/www/web# php artisan test

   PASS  Unit\ExampleTest
  ✓ basic test

   PASS  Feature\CommandTest
  ✓ コマンド実行

   PASS  Feature\ExampleTest
  ✓ basic test

   PASS  Feature\HomeTest
  ✓ 一覧表示

   PASS  Feature\LogInOutTest
  ✓ ログイン失敗
  ✓ ログイン成功
  ✓ ログアウト
  ✓ ログインしていないのにログアウト
  ✓ ログイン試行ブロック
  ✓ ログイン履歴
  ✓ パスワードリセット
  ✓ リセット失敗
  ✓ パスワードリセット可能か

   PASS  Feature\RssCategolyListTest
  ✓ r s sカテゴリ登録
  ✓ r s sカテゴリ編集
  ✓ r s sカテゴリ削除
  ✓ r s sカテゴリ二重登録

   PASS  Feature\RssListTest
  ✓ r s s登録
  ✓ r s s編集
  ✓ r s s削除
  ✓ r s s二重登録
  ✓ r s s編集その2

   PASS  Feature\UserTest
  ✓ ユーザ登録
  ✓ ユーザ登録パスワード短い
  ✓ ユーザ登録パスワード間違い
  ✓ ユーザ情報修正
  ✓ ユーザ削除
  ✓ ユーザ削除キャンセル

  Tests:  28 passed
  Time:   15.90s
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む