- 投稿日:2020-03-15T19:37:49+09:00
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.
- 投稿日:2020-03-15T19:16:18+09:00
【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.エラーに従って
users
のid
とhoge
のuser_id
をチェックすると
users.id
はBIGINT
hoge.user_id
はINT
型が違った
修正内容
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'); }); }
- 投稿日:2020-03-15T15:55:40+09:00
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だけど動いてるやん!
この記事で解決。
どうも、Google認証の「OAuth 2.0 クライアント ID」は、一度あるポートで使うと、その後で違うポートで利用することはできないらしい。
クイックスタートはMAMP(ポート80)で動かしていて、LaravelはLaravelサーバ(ポート8000)で動かしたためNGだった模様。
新しくOAuth 2.0 クライアント IDを作り直したら、あっさり解決。
- 投稿日:2020-03-15T15:52:15+09:00
laravelの学習のためにECサイトを作成した
- 投稿日:2020-03-15T11:35:34+09:00
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)投稿画面の作成
日記を投稿する画面を作ります。
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これでとりあえず動きました。
まとめ
とりあえず動く掲示板のような日記のようなものは完成。
今後はデザインの方に力を入れたり、ログイン機能を作ります。
- 投稿日:2020-03-15T07:46:14+09:00
商用環境でも使っている 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
に変更があった場合にしか走らないように工夫している。
composer.json
とcomposer.lock
をコンテナ内にコピーcomposer install --no-scripts --no-autoloader
で,スクリプト実行無しおよびオートローダ作成無しにして,vendor
ディレクトリへのファイル投入だけを目的として実行。- アプリケーションのコードをマウント。この際
vendor
ディレクトリは除外されている。composer dump-autoload -o
で後からオートローダを作成。- パッケージインストール高速化のため, Composer の並列インストールプラグイン hirak/prestissimo および日本国内ミラー Packagist.JP を使用している。
- 但し, Circle CI などでのビルドを考慮する場合はミラーではなく本家を参照したほうがいいかもしれない。
ARG
で分岐の余地あり。- GitHub のプライベートリポジトリからパッケージをインストールできるように, 会社の共用アカウントで発行したこの目的専用の
GITHUB_TOKEN
をARG
のデフォルト値としてハードコーディング。- エクステンションとして,さまざまな 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')
とか書いてしまうとそれが拾われてキャッシュされてしまい,キャッシュしないと動かないという歪んだ状態に陥ってしまうので注意する。この変数はアプリケーションからは参照してはいけない。
- 投稿日:2020-03-15T02:28:59+09:00
【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/
- 投稿日:2020-03-15T00:36:59+09:00
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