- 投稿日:2020-08-04T23:13:34+09:00
【Laravel】リポジトリパターン実装におけるエラー Target [App\Repositories\UserRepositoryInterface] is not instantiable while building
3行で
- Userリポジトリが読み込めない
- なぜか他のリポジトリは読める(例えばArticlesRepositoryとか)
- AppServiceProvider.php を見直す
概要
「マイページにユーザーが投稿した記事を、ユーザー名に基づいてArticlesテーブルから持ってくる」というパターンで実装する
リポジトリパターン実装における各ファイル
実装クラス
UserRepository.php<?php namespace App\Repositories\User; // Modelディレクトリを作るパターンで実装している use App\Models\User; class UserRepository implements UserRepositoryInterface { protected $user; /** * @param object $user */ public function __construct(User $user) { $this->user = $user; } public function getUser($name) { return $this->user->where('name', $name)->first(); } }インターフェース
UserRepositoryInterface.php<?php namespace App\Repositories\User; interface UserRepositoryInterface { public function getUser($name); }コントローラ
UserController.php<?php namespace App\Http\Controllers; use App\Repositories\User\UserRepositoryInterface; use App\Models\User; use Illuminate\Http\Request; class UserController extends Controller { protected $user; public function __construct(UserRepositoryInterface $userRepository) { $this->userRepository = $userRepository; } public function show(String $name) { $user = $this->userRepository->getUser($name); $articles = $user->articles->sortByDesc('create_at'); return view('users.show', [ 'user' => $user, 'articles' => $articles, ]); } }サービスプロバイダ
下記のコードでエラーが起きた。
AppServiceProvider.php<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * Register any application services. * * @return void */ /** * Bootstrap any application services. * * @return void */ public function boot() { // } // インターフェースと実装クラスを登録 public function register() { $this->app->bind( \App\Repositories\Article\ArticleRepositoryInterface::class, \App\Repositories\Article\ArticleRepository::class, \App\Repositories\User\UserRepositoryInterface::class, \App\Repositories\User\UserRepository::class ); } }これが問題だったが、自分の知る限り(あと調べた限り)ではこのパターンで実装できている。
3日くらい悩んだりいろいろ試してたらこの記事を見つけた。Target [App\Interfaces\User\UserInterface] is not instantiable while building #1
試しに修正してみる。↓
AppServiceProvider.php<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * Register any application services. * * @return void */ /** * Bootstrap any application services. * * @return void */ public function boot() { // } // インターフェースと実装クラスを登録 public function register() { $this->app->bind( \App\Repositories\Article\ArticleRepositoryInterface::class, \App\Repositories\Article\ArticleRepository::class ); $this->app->bind( \App\Repositories\User\UserRepositoryInterface::class, \App\Repositories\User\UserRepository::class ); } }そしたら直った。
理由が正直わからないのでもしわかる方がいたら教えてください。
- 投稿日:2020-08-04T23:11:03+09:00
【PHP・laravel】クエリパラメータを送る時まとめ(getとrequest)
初歩的なことですが、調べてもなかなか出てこなかったため、記録します。
HTMLからPHP側に送る
sample1.laravel.php<a harf="http://ここがURL?suji=1">送信</a>sample2.laravel.php<a harf="http://ここがURL?moji='文字'">送信</a>php側
index.php$get1 = $_GET['suji'];//1 $get2 = $_GET['moji'];//'文字'PHP内のやり取り(関数から関数)
数値や文字を送るとき
index.phpfunction a(){ redirect('/b?suji=1'); } function b(){ $request1 = $_REQUEST['suji']//1 }index.phpfunction a(){ redirect("/b?moji='文字'"); } function b(){ $request2 = $_REQUEST['moji']//文字 }変数を送るとき
index.phpfunction a(){ $count = 2; redirect('/b?count='.$count); } function b(){ $request3 = $_REQUEST['count']//2 }
- 投稿日:2020-08-04T20:00:57+09:00
Laravelのブログ開発でmarkdown対応させてみた
はじめに
Laravelを使ってブログを開発している際に見出しや装飾を本文に反映させてみたいな
と思い、markdown対応させてみました。
至らない点がありますが暖かい目でみてやってください。使用するmarkdown
Markdown Extraを使用します。
また、ライブラリはcebe\markdownを使用します。markdown実装
markdownの実装自体は簡単なコードで完了します。
convertMarkdown.php$converter = new \cebe\markdown\MarkdownExtra(); $String = $converter->parse("# AAA"); // <h1>AAA</h1>Laravelプロジェクトに組み込む
convertMarkdown.phpで使用したコードをLaravelプロジェクトに組み込みます。
今回はブログでの使用なのでブログの本文が表示される画面で反映させたいので、
記事一覧画面(index.blade.php)と記事詳細画面(show.blade.php)に以下のコードを組み込みます。index.blade.php&show.blade.php<div class="body"> @php $converter = new \cebe\markdown\MarkdownExtra(); $item->contents = $converter->parse($item->contents); @endphp {!! $item->contents !!} </div>
{!! !!}
でHTMLの要素をそのまま表示させています。(Laravel標準のhtmlspecialcharsを解除)動作確認
記事一覧画面
markdown反映前
markdown反映後
記事詳細画面
markdown反映後
終わりに
今回はLaravelを使ったブログにmarkdownを反映させる処理を書きました。
view部分にmarkdownの処理を書いたり、共通関数にしなかったりですっきりしたコードではないのですが、ひとまず実現できたのでOKとしています。
この記事に関して何かあればコメントや編集リクエスト投げていただけると幸いです!参考文献
- 投稿日:2020-08-04T18:00:57+09:00
Laravelのリソースコントローラのルーティング
Laravelのリソースコントローラのルーティング
参考:公式リファレンス$ php artisan make:controller PhotoController --resourceweb.phpRoute::resource('photos', 'PhotoController');このルーティング
Route::resource()
をバラして書くと以下のようになる。web.phpRoute::get('/photos', 'PhotoController@index')->name('photos.index'); Route::get('/photos/create', 'PhotoController@create')->name('photos.create'); Route::post('/photos', 'PhotoController@store')->name('photos.store'); Route::get('/photos/{photo}', 'PhotoController@show')->name('photos.show'); Route::get('/photos/{photo}/edit', 'PhotoController@edit')->name('photos.edit'); Route::put('/photos/{photo}', 'PhotoController@update')->name('photos.update'); Route::delete('/photos/{photo}', 'PhotoController@destroy')->name('photos.destroy');確認
$ php artisan route:list
出力結果
+--------+-----------+---------------------+----------------+----------------------------------------------+------------+ | Domain | Method | URI | Name | Action | Middleware | +--------+-----------+---------------------+----------------+----------------------------------------------+------------+ | | GET|HEAD | api/user | | Closure | api | | | | | | | auth:api | | | GET|HEAD | photos | photos.index | App\Http\Controllers\PhotoController@index | web | | | POST | photos | photos.store | App\Http\Controllers\PhotoController@store | web | | | GET|HEAD | photos/create | photos.create | App\Http\Controllers\PhotoController@create | web | | | GET|HEAD | photos/{photo} | photos.show | App\Http\Controllers\PhotoController@show | web | | | PUT|PATCH | photos/{photo} | photos.update | App\Http\Controllers\PhotoController@update | web | | | DELETE | photos/{photo} | photos.destroy | App\Http\Controllers\PhotoController@destroy | web | | | GET|HEAD | photos/{photo}/edit | photos.edit | App\Http\Controllers\PhotoController@edit | web | +--------+-----------+---------------------+----------------+----------------------------------------------+------------+
- 投稿日:2020-08-04T17:07:51+09:00
Laravelでテーブルのcreated_at, updated_atに時刻をミリ秒単位で入れる
初めに
PHP(laravel)の開発で、
データベースにinsertする際、created_at、updated_atの時刻を、ミリ秒(3桁)まで指定する要件があり、ネットで探しても良記事が見つからなかったのでメモ。1.getDateFormat()をModelに記載
例として、productsテーブルに商品を登録するという想定。
Product.phpnamespace App\Models; use Illuminate\Database\Eloquent\Model; class Product extends Model { //~省略~ //この関数をモデルに追加 public function getDateFormat() { return 'Y-m-d H:i:s.v'; } }2.現在時刻をミリ秒単位に成型
コントローラにDBの処理を書くことはバットプラクティスかもしれませんが、
今回簡単な例としてコントローラーに下記のように記述。
*Carbonを使用。
(PHP7.2以降であればdate()->format('Y-m-d H:i:s.v')でもミリ秒に変換できるみたいです)ProductController.php//carbonを利用 use Carbon\Carbon; function createProduct ($product) { //現在時刻をミリ秒に変更("2020-08-04 12:45:07.105"のような形式になる) $now = Carbon::now()->format('Y-m-d H:i:s.v'); $products = new Product(); //~略~ $products->created_at = $now; $products->updated_at = $now; $products->save() }これでcreated_at、updated_atからむに現在時刻がミリ秒の単位で登録される。
参考
https://stackoverflow.com/questions/50208932/laravel-model-trailing-data-when-save-the-model
https://hnw.hatenablog.com/entry/20180401
- 投稿日:2020-08-04T16:43:40+09:00
laravelを使ったときにハマったエラーの解決方法
状況
laravel new laravelappMacでlaravelをインストールして上記のlaravelコマンドを使おうとするとこんなエラーが出た。
[RuntimeException] The Zip PHP extension is not installed. Please install it and try again.こちらのエラーの解消に大分時間を費やしたので、同じエラーにハマってる人のために記事を残しておこうと思う。
解決方法
composerのインストール
まずはcomposerをインストールする
下記をターミナルで実行するbrew install composercomposerコマンドを代わりに使う
laravel new laravelappmacの場合これでは無理なので代わりに,composer経由で行う。
composer create-project --prefer-dist laravel/laravel test_apptest_appは作りたいアプリ名。
このコマンドが使えない場合はパスが通ってない可能性があるので、下記を実行してください。
echo "export PATH=~/.composer/vendor/bin:$PATH" >> ~/.zprofile source ~/.zprofile解決方法2
composerコマンドを使って自分の場合は解決できたのですが、それでは解決できないこともあるかもしれません。
そういう場合はdockerを使うことを勧めます。
https://github.com/hiroto2929/laravel_docker
こちらを参考に環境構築してください。
参考記事
エラーについて調べた際に出てきた記事
https://qiita.com/endeavor/items/77f7017473c95c42fc29
https://iiiso.ti-da.net/e8647248.html
- 投稿日:2020-08-04T15:17:18+09:00
CakePHP3.8 と Laravel7.x の「書き方」の違い ~ORM周りその2~
CakePHP3.8 と Laravel7.x の「書き方」の違い ~ORM周りその2~
今回はアクセサー周り
前: クエリの要約
そもそもクエリオブジェクトの返り値が別
1件取得
- CakePHP
Table クラスとは別に、Entity クラスがあり、それが返ってくる
// \App\Model\Entity\Users が返ってくる(Table クラスとは別) $veteranHyphen = $usersTable->find('hyphen')->find('veteran')->first();
- Laravel
Model が Cake で言う Table, Entity の役割を持っている。
なので Model 自身のインスタンスが返ってくる。// \App\Users が返ってくる $veteranHyphen = Users::hyphen()->veteran()->first();複数件取得
- CakePHP
Collection インスタンスが返ってくる。
Collection の要素には Entity インスタンスが入っている。// \Cake\Collection\Collection $veteranHyphenUsers = $usersTable->find('hyphen')->find('veteran')->all(); foreach ($veteranHyphenUsers as $veteranHyphenUser) // 中身は \App\Model\Entity\Users
- Laravel
Collection インスタンスが返ってくる。
Collection の要素には Model インスタンスが入っている。// \Illuminate\Database\Eloquent\Collection $veteranHyphenUsers = Users::hyphen()->veteran()->get(); foreach ($veteranHyphenUsers as $veteranHyphenUser) // 中身は \App\Usersアクセサー
fetch したレコードの値を、参照するときにフォーマットすることができます。
DB からとってくるとき、ちょっとした整形が面倒くさいなぁ(CASE文大量など)といったときに便利です。個人的には表示系をここに書いても良いんじゃないかなって思います。
(郵便番号 => 住所 とか 0,1 => 男女 とか)
- CakePHP
CakePHP では「仮想プロパティ」と呼ばれています。
Entity クラスの中で、「_get」+ {仮想プロパティ名}で定義できます。namespace App\Model\Entity; use Cake\ORM\Entity; class User extends Entity { protected function _getFullName() { return $this->_properties['first_name'] . ' ' . $this->_properties['last_name']; } } // 参照する時 echo $user->full_name; // 横丁 小町仮想プロパティはデータを保存するときには干渉しません。
- Laravel
Laravel では「アクセサ」と呼ばれています。
get + {プロパティ名} + Attribute で定義できます。namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * ユーザーのフルネームを取得 * * @return string */ public function getFullNameAttribute() { return $this->first_name . ' ' . $this->last_name'; } } // 参照する時 echo $user->full_name; // 横丁 小町保存時にも影響を与えたい時
入力した値を、自動的に保存時にフォーマットしてほしい時
- CakePHP3
ややこしいですが、CakePHP ではこれを アクセサ と呼びます。
値を参照するときにはもちろん、DBにデータを保存するときにも適用されます。値を保存する時、値を参照する時、両方向に影響があるので、冪等性が担保されていなければなりません
namespace App\Model\Entity; use Cake\ORM\Entity; class Article extends Entity { protected function _getTitle($title) { return ucwords($title); } }
- Laravel
Laravel では、カスタムキャスト でこれを実現します。
CakePHPと違って、値を取得する時、保存する時で処理を分けられるので、冪等性をそんなに気にしなくても良いです。キャストを定義して、
namespace App\Casts; use Illuminate\Contracts\Database\Eloquent\CastsAttributes; class Ucwords implements CastsAttributes { /** * 指定された値をキャストする * * @param \Illuminate\Database\Eloquent\Model $model * @param string $key * @param mixed $value * @param array $attributes * @return array */ public function set($model, $key, $value, $attributes) { return ucwords($value); } }Model で設定
namespace App; use App\Casts\Ucwords; use Illuminate\Database\Eloquent\Model; class Article extends Model { /** * キャストする属性 * * @var array */ protected $casts = [ 'title' => Ucwords::class, ]; }おわりに
フレームワークごとに単語を統一してほしい。
- 投稿日:2020-08-04T14:43:40+09:00
2020年のLaravelパフォーマンス最適化のための12のヒント
概要
12 Tips for Laravel Performance Optimization in 2020
から引っ張ってきたものです。結構Google翻訳の質が向上していた。掻い摘んで抜粋していきます。
目次
- 構成キャッシング
- ルートキャッシング
- 未使用のサービスを削除
- クラスマップの最適化
- Composer最適化オートロード
- 含まれるライブラリを制限する
- JITコンパイラ
- Fast Cache and Sessionドライバーを選択する
- クエリ結果のキャッシュ
- Eager loadingを使用する
- アセットのプリコンパイル
- PHPの最新バージョンを実行する
- CDNを使う
- アセットバンドル
- ファイル圧縮
- PHPの最新バージョンを実行する
- Laravelデバッグバー
- Laravelの一般的なパフォーマンスチューニングのヒント
12のヒントという割には結構項目が多い...前提条件
- Laravel 5.5
- PHP 7.1
- MySQL (Version不明)
1. 構成キャッシング
Artisan Cache Configでパフォーマンスを向上させます。
$ php artisan config:cache設定を更新する場合は、キャッシュをクリアしましょう。
$ php artisan config:clearアプリケーションをさらに最適化するには、PHPコードをキャッシュするOPcacheを使用して、再コンパイルする必要がないようにします。
OPcache PHP公式ドキュメント2. ルートキャッシング
$ php artisan route:cacheconfigまたはroutesファイルが変更されるたびにコマンドを実行することを忘れないでください。
キャッシュをクリアするには、次のコマンドを使用します。
$ php artisan route:clear3. 未使用のサービスを削除
設定ファイルで未使用のサービスを必ず無効にしてください。
使用していないサービスプロバイダーにコメントアウトを追加します。4. クラスマップの最適化
$ php artisan optimize --force5. Composer最適化オートロード
$ composer dumpautoload -o6. 含まれるライブラリを制限する
ライブラリなしで実行できると思われる場合は、
config/app.php
から削除してLaravelアプリを高速化します。もう1つの重要な場所はcomposer.json
です。7. JITコンパイラ
Laravelアプリの場合、推奨されるJITコンパイラはFacebookのHHVMです。
@ytake さんからの指摘です。
HHVM4.0以降はPHPの動作をサポートしていませんので、
現時点でHHVM上でLaravelを動かすのはお勧めしません。(PHPのコードはもう動きません)
現在の最新バージョンはPHP互換環境ではなくなっていますよ。8. Fast Cache and Sessionドライバーを選択する
Laravel5のパフォーマンスのための最速のキャッシュおよびセッションドライバーはMemcachedだと思われます。
セッションドライバーを変更するためのドライバーキーは、通常
app/config/session.php
にあります。同様に、キャッシュドライバーを変更するためのドライバーキーはapp/config/cache.php
にあります。9. クエリ結果のキャッシュ
頻繁に実行されるクエリの結果をキャッシュすることは、Laravel5.5のパフォーマンスを向上させる優れた方法です。
次のように使用される記憶機能をお勧めします。$posts = Cache::remember('index.posts', 30, function(){ return Post::with('comments', 'tags', 'author', 'seo')->whereHidden(0)->get(); });10. Eager loadingを使用する
Eloquentは最初のクエリに応答して、関連付けられているすべてのオブジェクトモデルを取得します。これにより、アプリケーションの応答が増加します。
遅延ローディングの例です。
$books = App\Book::all(); foreach ($books as $book) { echo $book->author->name; }Eager loadingの例です。
$books = App\Book::with('author')->get(); foreach ($books as $book) { echo $book->author->name; }11. アセットのプリコンパイル
$ php artisan optimize $ php artisan config:cache $ php artisan route:cache12. CDNを使う
CDNサーバーから静的アセットファイルをロードすると(ファイルをホストするサーバーから直接ロードするのではなく)、Laravelアプリケーションのパフォーマンスが向上します。
13. アセットバンドル
Laravel Mixで複数のスタイルシートやJSファイルを1つのファイルに効率的に連結できます。
webpack.mix.jsmix.styles([ 'public/css/vendor/normalize.css', 'public/css/styles.css' ], 'public/css/all.css');14. ファイル圧縮
Laravel Mixを使用してアセットを縮小できます。
$ npm run production15. PHPの最新バージョンを実行する
PHPの最新バージョンでは、パフォーマンスが大幅に向上しています。したがって、Laravelアプリケーションが最新バージョンのPHPを実行していることを確認して、アプリケーションの新しいバージョンで導入されたすべてのパフォーマンス改善を活用できるようにします。
16. Laravelデバッグバー
最適化手法ではなく、パッケージです。Laravel Debugbarは、PHPデバッグバーをLaravel 5と統合するためのパッケージです。
ServiceBarには、デバッグバーを登録して出力に添付するServiceProviderが含まれています。
Laravelパフォーマンスモニターとして使用できるパッケージです。アプリケーションの開発中にこのパッケージを使用することをお勧めします。
これにより、アプリケーションの実行状況を簡単に検査して、それに応じて改善することができます。
17. Laravelの一般的なパフォーマンスチューニングのヒント
Webサイトのパフォーマンスを最適化するには、次のようないくつかの調整を実装するだけです。
- Laravelページスピードコンポーザーパッケージ
- プロバイダーの詳細を更新する
- パッケージを公開する
- ミドルウェアを登録する
- ページ上にルートを作成する
- ブレードファイルを作成
- アプリを実行
Laravelページスピードコンポーザーパッケージ
Composerを使用して、
renatomarinho/laravel-page-speed
パッケージをダウンロードと展開します。$ composer require renatomarinho/laravel-page-speedプロバイダーの更新
config/app.php
ファイルに移動し、サービスプロバイダーとエイリアスを展開します。config/app.php'providers' => [ .... .... RenatoMarinho\LaravelPageSpeed\ServiceProvider::class,パッケージの公開
$ php artisan vendor:publish --provider="RenatoMarinho\LaravelPageSpeed\ServiceProvider"Webアクセス用のミドルウェアを追加し、ルーティングに追加する
Kernel.phpprotected $middlewareGroups = [ 'web' => [ ........ ........ \RenatoMarinho\LaravelPageSpeed\Middleware\InlineCss::class, \RenatoMarinho\LaravelPageSpeed\Middleware\ElideAttributes::class, \RenatoMarinho\LaravelPageSpeed\Middleware\InsertDNSPrefetch::class, \RenatoMarinho\LaravelPageSpeed\Middleware\RemoveComments::class, \RenatoMarinho\LaravelPageSpeed\Middleware\TrimUrls::class, \RenatoMarinho\LaravelPageSpeed\Middleware\RemoveQuotes::class, \RenatoMarinho\LaravelPageSpeed\Middleware\CollapseWhitespace::class, ] ]web.php// Define Route // I going to add a route to check Optimized Website Speed and Performance in Laravel 5.5 Route::get('/listView', function () { return view('listView'); });カスタムスタックによるパフォーマンスの向上
ThunderStackとして知られるカスタムスタックは、Laravelアプリのパフォーマンスを向上させるように設計されています。受賞したレシピは、ApacheとNGINX、Varnish、Memcachedで構成されています。
参考
12 Tips for Laravel Performance Optimization in 2020
感想とか
Laravelアプリが遅い。重い。
色々言われている所もあると思いますが、パフォーマンスチューニングで実施できることは結構ありますね。
すっごい遅いし重いしLaravelクッソだなぁと思ってブーメラン
- 投稿日:2020-08-04T13:22:37+09:00
Laravelで和暦を扱う
和暦を扱う必要があったので,その実装をまとめてみました
環境
- Laravel 5.8
作るもの
- 年号を管理するテーブル(era_names)
- 和暦クラス
- 和暦と西暦の変換処理
年号テーブルの作成
年号を管理するテーブルには
- 年号の名前
- 略称
- 開始日
- 終了日
の4つのカラムを作成します.テーブル名を
era_names
とし,マイグレーションファイルは次のようになります.public function up() { Schema::create('era_names', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('short_name'); $table->date('start_at'); $table->date('end_at'); $table->timestamps(); }); }作成したマイグレーションを実行しテーブルを作成したら,モデルを作成します.
app\Models\EraName.phpclass EraName extends Model { /** @var string */ protected $table = 'era_names'; /** @var array */ protected $dates = [ 'start_at', 'end_at', ]; /** @var array */ protected $guarded = [ 'id', ]; }最後にデータを追加します.追加する方法はシーダやtinkerを用いてください.
name short_name start_at end_at 昭和 S 1926-12-25 1989-01-07 平成 H 1989-01-08 2019-04-30 令和 R 2019-05-01 2100-01-01 和暦-西暦変換処理の作成
プロジェクトの方針にしたがって,和暦-西暦の変換処理を作成します.ここでは和暦クラスを作成し,Carbon(CarbonImmutable)と相互変換する形で実装します.他の実装として変換処理をすべてServiceに書き,ファサードやヘルパを通して変換することなどが考えられます.
Carbonに和暦への変換メソッドを実装するために,次のようなサービスプロバイダを用意します.
app\Providers\DateServiceProvidernamespace App\Providers; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Facades\Date; use App\Models\EraName; use App\Models\Wareki; use Carbon\CarbonImmutable; class DateServiceProvider extends ServiceProvider { /** * Register any application services. * * @return void */ public function register() { Date::use(CarbonImmutable::class); // 日付を扱うクラスをCarbonImmutableに変更 Date::macro('toWareki', function () { // 日付を扱うクラスにtoWarekiメソッドを追加 return new Wareki($this); }); } /** * Bootstrap any application services. * * @return void */ public function boot() { $this->app->instance('era_names', EraName::all()); // サービスコンテナに年号を登録 } }
Date::macro(...)
を用いることで,日付オブジェクトにメソッドを追加することができます.ここではtoWareki
メソッドを追加しています.$this->app->instance('era_names', EraName::all());この部分ではサービスコンテナに年号を登録し,どこでも同じインスタンスが取得できるようにします.取得方法は
app('era_names')で取得することができます.これを行うことで,処理の途中でera_namesテーブルの内容が変更されても,処理開始時の年号データが使われるようになります.また,年号を取得するSQLが1度しか実行されなくなるなどの利点があります.
次に和暦クラスを実装します.場所はプロジェクトの方針にしたがいましょう.ここでは
app\Models
下に作成します.app\Models\Wareki.phpnamespace App\Models; use Illuminate\Support\Facades\Date; use Carbon\CarbonImmutable; use App\Models\EraName; class Wareki { /** @var int */ public $year; public $fiscalYear; public $month; public $day; /** @var EraName */ public $eraName; /** * @param Carbon|CarbonImmutable */ public function __construct($ymd) { $this->eraName = app('era_names')->first(function ($eraName) use ($ymd) { return $eraName->start_at->startOfDay() <= $ymd && $ymd <= $eraName->end_at->endOfDay(); }); $this->year = $ymd->year - $this->eraName->start_at->year + 1; $this->fiscalYear = $this->year - ((1 <= $ymd->month && $ymd->month <= 3) ? 1 : 0); $this->month = $ymd->month; $this->day = $ymd->day; } /** * @return Carbon|CarbonImmutable */ public function toYmd() { return Date::createMidnightDate( $this->eraName->start_at->year + $this->year - 1, $this->month ?? 1, $this->day ?? 1, ); } /** * @param string $format * @return string */ public function format(string $format) { $ret = ''; foreach (mb_str_split($format) as $str) { if ($str === 'Y') $ret .= sprintf('%s%02d', $this->eraName->name, $this->year); else if ($str === 'S') $ret .= sprintf('%s%02d', $this->eraName->short_name, $this->year); else if ($str === 'y') $ret .= sprintf('%s%02d', $this->eraName->name, $this->fiscalYear); else if ($str === 's') $ret .= sprintf('%s%02d', $this->eraName->short_name, $this->fiscalYear); else if ($str === 'm') $ret .= sprintf('%02d', $this->month); else if ($str === 'd') $ret .= sprintf('%02d', $this->day); else $ret .= $str; } return $ret; } }和暦-西暦の変換処理は和暦クラスにまとめることにしてあります.コンストラクタで西暦->和暦の変換を行い,
toYmd
メソッドで和暦->西暦の変換を行います.format
メソッドでは和暦を文字列に変換します.例えば$ymd = Date::parse('2019-03-01'); \\ 平成年31年3月1日 $ymd->toWareki()->format('Y年'); \\ 平成31年 $ymd->toWareki()->format('S'); \\ H31 $ymd->toWareki()->format('y年度'); \\ 平成30年度 $ymd->toWareki()->format('s'); \\ H30 $ymd->toWareki()->format('m月d日'); \\ 03月01日このようになっています.この和暦クラスでは時分秒を扱わない形で実装しています.
まとめ
Laravelで和暦を扱ってみました.年号データをDBではなくconfigなどに設定する場合も,
$this->app->instance()
の部分を調整することで実装することができます.また,Data::macro
を用いて年度初めを取得する処理などを追加してもいいかもしれません.
- 投稿日:2020-08-04T10:20:58+09:00
Laravel5.6以降のログの機能をちょっと調べた
目的
- Laravelのログに関する情報を調べてみたので簡単にまとめる
実施環境
- ハードウェア環境
項目 情報 OS macOS Catalina(10.15.5) ハードウェア MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) プロセッサ 2 GHz クアッドコアIntel Core i5 メモリ 32 GB 3733 MHz LPDDR4 グラフィックス Intel Iris Plus Graphics 1536 MB
- ソフトウェア環境
項目 情報 備考 PHP バージョン 7.4.3 Homwbrewを用いて導入 Laravel バージョン 7.0.8 commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う MySQLバージョン 8.0.19 for osx10.13 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする 前提情報
- Laravelのログ出力方法はMonologと言う名前のライブラリを使用している。
- 本記事より公式ドキュメントの方がわかりやすいかもしれない。ログについて詳しく書いてあるLaravel5.6のドキュメントのリンクを下記に記載する。
ログチャンネル
- ログの出力にはチャンネルと言う機能を使用する。
- チャンネルは複数存在する。
- チャンネル = ログ出力の方法と考えていただいても差し支えないと思う。
下記にログチャンネルの種類を記載する。
チャンネル 説明 stack チャンネルをまとめるためのチャンネル single シングルチャンネル、一つのファイルにずっとログを書き込む。デフォルトの設定はこれ daily デイリーチャンネル一日毎にファイルを分けてログを出力してくれる。デフォルトだと14日間ログファイルを保持する。 slack slackチャンネル、社内のコミュニケーションツールであるslackにログを送信するためのチャンネル syslog システムログチャンネル、アプリのシステムログを出力するためのチャンネル errorlog エラーログチャンネル、エラーメッセージを出力するためのチャンネル monolog そのほかのライブラリで定義されているログを出力するためのチャンネル custom カスタムチャンネル、開発者が任意のチャンネルを作成するためのチャンネル 公式ドキュメントのログチャンネルの表を下記に記載する。
ログレベル
- laravelのログにはレベルが存在する。
- 出力の優先度によってレベル分けされている。
- 8個のレベルが存在し、最も重要性の高いログのレベル名はemergencyで開発段階の情報など重要度の低いログを出力するレベルはdebugとなる
- ログのレベルはチャンネル毎に設定可能である。ログ出力の指令を行うコードでも、出力したいログのレベルを指定することができる。
ログレベルの種類を下記に記載する。上位に行けば行くほど危険度が高いログレベルとして設計することが一般的である。
ログレベル emergency alert critical error warning notice info debug ログレベルは下記の規約で決められたものを使用している。
ログレベルはアプリ開発段階でのログに出力したい情報とデプロイしてユーザが使用している段階でのログに出力したい情報を分けるために存在する。
後述するログの設定ファイルでdebugを選択していれば全てのログレベルのログがログファイルに記載される。
後述するログの設定ファイルでを選択していれば全てのログレベルのログがログファイルに記載される。
ログの設定ファイル
- laravel5.6からログの設定ファイルの場所が変更になった。
アプリ名ディレクトリ/config/
直下のlogging.phpファイルがログの設定ファイルである。下記にloggingファイルの内容を記載する。
アプリ名ディレクトリ/config/loggign.php<?php use Monolog\Handler\NullHandler; use Monolog\Handler\StreamHandler; use Monolog\Handler\SyslogUdpHandler; return [ /* |-------------------------------------------------------------------------- | Default Log Channel |-------------------------------------------------------------------------- | | This option defines the default log channel that gets used when writing | messages to the logs. The name specified in this option should match | one of the channels defined in the "channels" configuration array. | */ 'default' => env('LOG_CHANNEL', 'stack'), /* |-------------------------------------------------------------------------- | Log Channels |-------------------------------------------------------------------------- | | Here you may configure the log channels for your application. Out of | the box, Laravel uses the Monolog PHP logging library. This gives | you a variety of powerful log handlers / formatters to utilize. | | Available Drivers: "single", "daily", "slack", "syslog", | "errorlog", "monolog", | "custom", "stack" | */ 'channels' => [ 'stack' => [ 'driver' => 'stack', 'channels' => ['single'], 'ignore_exceptions' => false, ], 'single' => [ 'driver' => 'single', 'path' => storage_path('logs/laravel.log'), 'level' => 'debug', ], 'daily' => [ 'driver' => 'daily', 'path' => storage_path('logs/laravel.log'), 'level' => 'debug', 'days' => 14, ], 'slack' => [ 'driver' => 'slack', 'url' => env('LOG_SLACK_WEBHOOK_URL'), 'username' => 'Laravel Log', 'emoji' => ':boom:', 'level' => 'critical', ], 'papertrail' => [ 'driver' => 'monolog', 'level' => 'debug', 'handler' => SyslogUdpHandler::class, 'handler_with' => [ 'host' => env('PAPERTRAIL_URL'), 'port' => env('PAPERTRAIL_PORT'), ], ], 'stderr' => [ 'driver' => 'monolog', 'handler' => StreamHandler::class, 'formatter' => env('LOG_STDERR_FORMATTER'), 'with' => [ 'stream' => 'php://stderr', ], ], 'syslog' => [ 'driver' => 'syslog', 'level' => 'debug', ], 'errorlog' => [ 'driver' => 'errorlog', 'level' => 'debug', ], 'null' => [ 'driver' => 'monolog', 'handler' => NullHandler::class, ], 'emergency' => [ 'path' => storage_path('logs/laravel.log'), ], ], ];ログチャンネルの指定
- どのログチャンネルを指定してログを出力するのかの設定は
アプリ名ディレクトリ/
直下にある.envファイルに記載する。.envの下記の部分でログチャンネルの設定を行っている。
アプリ名ディレクトリ/.envLOG_CHANNEL=stack上記の様に記載されていると、stackチャンネル(チャンネルをまとめるためのチャンネル)が選択されていることになる。
dailyチャンネルでログを出力したい場合は下記の様に.envファイルに記載する。
アプリ名ディレクトリ/.envLOG_CHANNEL=daily複数のログを出力するための方法は下記の記事にまとめてみた。(stackチャンネルに出力したいログチャンネルを配列状に追加することがセオリーの様である。)
ログの初期設定の状態
$ laravel new アプリ名
を実行した直後の何もいじっていない状態のログの設定がどうなっているのか確認してみる。
アプリの設定ファイルである.envファイルのログチャンネルの設定の確認
下記に.envファイルのログチャンネルの記載部分のみ抜粋して記載する。
アプリ名ディレクトリ/.envLOG_CHANNEL=stackログチャンネルはstackが選択されている。
ログの設定ファイルlogging.phpの記載の確認
下記にlogging.phpファイルの内容を記載する。
アプリ名ディレクトリ/config/loggign.php<?php use Monolog\Handler\NullHandler; use Monolog\Handler\StreamHandler; use Monolog\Handler\SyslogUdpHandler; return [ /* |-------------------------------------------------------------------------- | Default Log Channel |-------------------------------------------------------------------------- | | This option defines the default log channel that gets used when writing | messages to the logs. The name specified in this option should match | one of the channels defined in the "channels" configuration array. | */ 'default' => env('LOG_CHANNEL', 'stack'), /* |-------------------------------------------------------------------------- | Log Channels |-------------------------------------------------------------------------- | | Here you may configure the log channels for your application. Out of | the box, Laravel uses the Monolog PHP logging library. This gives | you a variety of powerful log handlers / formatters to utilize. | | Available Drivers: "single", "daily", "slack", "syslog", | "errorlog", "monolog", | "custom", "stack" | */ 'channels' => [ 'stack' => [ 'driver' => 'stack', 'channels' => ['single'], 'ignore_exceptions' => false, ], 'single' => [ 'driver' => 'single', 'path' => storage_path('logs/laravel.log'), 'level' => 'debug', ], 'daily' => [ 'driver' => 'daily', 'path' => storage_path('logs/laravel.log'), 'level' => 'debug', 'days' => 14, ], 'slack' => [ 'driver' => 'slack', 'url' => env('LOG_SLACK_WEBHOOK_URL'), 'username' => 'Laravel Log', 'emoji' => ':boom:', 'level' => 'critical', ], 'papertrail' => [ 'driver' => 'monolog', 'level' => 'debug', 'handler' => SyslogUdpHandler::class, 'handler_with' => [ 'host' => env('PAPERTRAIL_URL'), 'port' => env('PAPERTRAIL_PORT'), ], ], 'stderr' => [ 'driver' => 'monolog', 'handler' => StreamHandler::class, 'formatter' => env('LOG_STDERR_FORMATTER'), 'with' => [ 'stream' => 'php://stderr', ], ], 'syslog' => [ 'driver' => 'syslog', 'level' => 'debug', ], 'errorlog' => [ 'driver' => 'errorlog', 'level' => 'debug', ], 'null' => [ 'driver' => 'monolog', 'handler' => NullHandler::class, ], 'emergency' => [ 'path' => storage_path('logs/laravel.log'), ], ], ];コード
'default' => env('LOG_CHANNEL', 'stack'),
では.envファイルにてログチャンネルの設定が行われなかった場合に指定されるデフォルトのログチャンネルが記載されている。デフォルトではログチャンネルの設定が.envファイルにて行われなかった場合、stackチャンネルを指定する様に記載されている。本記載は基本的に変更しない。配列状に格納されているログチャンネルの情報について説明する。下記に.envファイルで指定されているstackチャンネルの記載部分のみ抜粋したコードを記載する。
アプリ名ディレクトリ/config/loggign.php'stack' => [ 'driver' => 'stack', //ライブラリの実行ドライバを指定している(チャンネル名を指定していると考えていただきたい) 'channels' => ['single'], //まとめて実行するログチャンネルを配列状に指定している デフォルトだとsingleチャンネルのみが指定されている。 'ignore_exceptions' => false, //本記載の意味を現在調査中です。 ],ログチャンネルを変更するには?
- デフォルトのログチャンネルから変更する方法は主に二通りあると考える。下記に二通りの方法を記載する。
- .envファイルにて
LOG_CHANNEL=
の記載を設定したいログチャンネルに変更する。- .envファイルの
LOG_CHANNEL=
の記載は弄らずに「stack」チャンネルを選択し、アプリ名ディレクトリ/config/loggign.php
の「stack」チャンネルの設定部分'channels' =>
にて出力チャンネルを変更する。- 単一のログのみを出力するなら.envにてログチャンネルを設定するだけで良いが、「single」チャンネルと「daily」チャンネル両方のログが欲しい時は
アプリ名ディレクトリ/config/loggign.php
の「stack」チャンネルの設定部分で指定する必要がある。下記に筆者が以前まとめた二種類のログを出力する方法の記事のリンクを記載する。参考文献
- 投稿日:2020-08-04T06:35:54+09:00
助産師が退職して1年後に初めてアプリリリース
Qiita久しぶりです!
毎日自分のブログを更新するので精一杯のため全然書けませんでした(という言い訳w)。
大学病院で助産師としての仕事を退職してちょうど1年、
プログラミングを勉強して10ヶ月で初めて簡単なアプリをリリースしたので、
ここまでの経緯を簡単に振り返りたいと思います。
(まぁまぁ長くなってしまったので興味がある部分だけサラーっと読んで下さいw)アプリリリースを決めるの簡単な振り返り
ジーズアカデミーで半年、プログラミング必死に勉強
マジで大変でした〜
病院の古いUI電子カルテしか使ったことない私が急にコード書くって、
昭和時代にタイムスリップしてそこの人にiPhone渡して「ググって〜」と言うのと同じです。
つまりさっぱりなんです。
だからすごい大変でした、でも私なりに出来る努力をしました。関連記事
学校と家事と育児の2ヶ月半を振り返って在学中にサーバーサイドインターン
勉強すればする程、こんなポンコツな自分では開発とかITで業界良くするとかマジで無理!
と思い一旦エンジニア就職しようと決めます。
あまりにも扱える武器が少なすぎる。だから在学中にインターン先を探しました。
ありがたいことにとある医療系ベンチャー企業でインターンをさせて頂くことになりました。開発言語はRuby, フレームワークrails。
今までPHPとLaravelしかしたことない私にとっては不安しかありませんでしたが、
それでももう会社を選んでいる余裕なんて余裕でありません。
業界未経験育児中30overの私がインターンできるだけでも奇跡です。
ここは頑張るしかありません。幸いにもLaravelのおかげでMVCをなんとなく理解していたので、
railsはすんなり入ってきました。
Rubyの書き方も直感的にわかる部分もありました。
わからないメソッドや書き方はその都度調べました。
優しいエンジニアの方にかなり助けられながら毎日必死になんとか這いつくばりました。そしてやっぱり一番学び、毎日強く感じたのは、
個人開発と会社の開発の圧倒的なスケールの違いです。
インターンをすればする程、自分の開発はおもちゃに感じました。
関連記事
webサービスの質卒業制作発表会(GGA)で優勝
日中ほぼフルタイムでインターンをしながらGGAの準備をしました。
ちょうど子ども達の自粛期間だったので、正直ここが一番大変でした。
容赦ないインターンの開発と発表の準備、でも日中は子ども3人が自宅にいます。
夫にもかなり協力してもらい、なんとインターンの開発を進めながら発表の準備も進めました。
発表会の結果はまさかのまさか、ポンコツな私が優勝しました。関連記事
卒業制作発表会が終わりました
優勝と卒業想定外の結果に正直驚き、
卒業後「本当にエンジニア就職で良いのか?」と自分の中で考えました。
そしてとりあえず自分のやりたいことをできる所までやってみよう!
そういう結論に至りました。関連記事
とりあえずやってみる
会社を設立する意味会社設立
インターンをしながらとりあえず会社も設立しました。
インターンが終了したすぐに動けるように手続き関連はチョコチョコと進めていました。
https://nsmart.workインターン終了
この機会をを逃すとエンジニアにはもうなれない、そんなん重々承知の上でインターンを終了することになりました。
3ヶ月、たくさんのことを教えてくれたエンジニアの方には本当に感謝してもしきれません。
関連記事
エンジニアインターン終了とりあえず1つリリースしてみよう
これから会社としてどうするか、ビジネスのビの字も知らない私なりに考えました。
たくさん考えたし今も毎日考えていますが、
とりあえず発表会で作ったアプリを1つリリースしてみよう、そう思いました。
幸いにも私の想いに共感してくれたジーズアカデミーの同期2人が開発を手伝ってくれることになり、
発表会よりもブラッシュアップしてアプリをリリースすることになりました。アプリリリースまで
アプリの機能
機能は時間を計算するという非常にシンプルなアプリです。
陣痛が始まった時間〜胎盤が出たまでの時間(いわゆるお産何時間かかりました、とうやつです。専門用語で分娩所要時間と言います)を計算します。
この時間計算を、電子カルテがない産院では助産師や看護師が頭で計算しているという実情があります。
例えば、
陣痛が始まった時間 7/30 11:10
胎盤が出た時間 8/1 0:21
この間が何時間何分かをすぐに計算できる人はほぼいないと思います。
これを陣痛が始まった時間と胎盤が出た時間だけ入力したらすぐに計算できるという昨日です。
これしか出来ません!
だから卒業した時は、HTMLとCSS,JSでさらっと作りました。
時間計算は moment.jsというライブラリーを使いました。アプリの改善点
計算項目の追加
実はこの分娩所要時間、時期にⅠ期 Ⅱ期 Ⅲ期と分かれています。
Ⅰ期+Ⅱ期+Ⅲ期=分娩所要時間
となります。
どうせだったらこのⅠ期 Ⅱ期 Ⅲ期も出して欲しい、
これが私の友人助産師5人にヒアリングしてほぼ一致した意見でした。
確かにそれはそうや!
よって本来の分娩所要時間にプラスしてⅠ期 Ⅱ期 Ⅲ期も出せるように項目を増やしました。dbとの接続
マジでHTMLとCSS,JSだけで作っていたのですが、それではこのアプリをリリースした時にどれくらいユーザーがいてどれくら使われているか全くわかりません。
よって、簡単な会員登録をしてログインして頂き、計算した値をdbに飛ばす設計にしました。
Laravelとmysqlを使用して実装しました。
これでどれくらいの人が使っているのかわかるので、インフラを増強するタイミングもわかります。
あとは些細ですが会社の実績にもなるかなと思いました。PWA
可能な限りネイティブアプリに近くしたい。
忙しい現場の看護職にいちいちsafari開いてお気に入りからアプリのURL探して、
もしくはいちいちQRコード読み取っては面倒くさ過ぎます。
でももちろん私にはネイティブアプリにするお金も技術もありません。
よってPWAを実装することにしました。
調べながらなんとか実装しました。
正直これが一番難しかった・・・
多分まだあまりわかっていない・・・開発以外でしたこと
アプリ紹介のLP作成
これはお洒落でセンスの良い友人達がほぼしてくれました。
ダサい私にはこんなお洒落なサイト作れません!!
PWAの利用方法もわからない方がほとんどなので、ここもなるべく丁寧にわかりやすく説明したPDFを作ってもらいました。
https://nsmart.work/app1実機テスト
私含めて3人の自宅にあるありとあらゆる端末で実機テストです。
幸いにもインターンで総合テストをどのように実施しているのか一部拝見できたので、
それを参考にスプレッドシートに項目をまとめて各自自宅で実機テストをしました。
そしてテストすればする程、細かい修正点が出る出る・・・
工程数少なくて優先順位高いものから潰しましたアプリリリースしての感想
自分が思っていたものが形になり現場の看護職に使ってもらえるかもしれないというのは本当に感慨深いものがあります。
まだ正直信じられません。
1年前の私では1ミリも想像できなかったことです。
ここまで一緒に手伝ってくれた友人に本当に心の底から感謝しています。新たなサービス開発
この開発したアプリの発展バージョンの構成もあるのですがそれはもう少しお金がなんとかなったら作りたいなと思っています。
今は少しまた別のサービスを開発予定です(昨夜開発のキックオフテレカンしまました)。
と言っても現場で働く看護職の業務改善に特化したアプリです。今回のアプリに比べるとかなり手が込んでいて正直どこまで実装できるかわかりません。
私含めてジーズアカデミーの同期3人、計4人でLaravelとvueで開発します。
今の我々でできる最高のプロダクトを作りたいと思っています。
もしかしたらそれはエンジニアの方からするとおもちゃかもしれません。
でも最高のおもちゃを作りたいと思います。インフラやセキュリティ関連が弱弱なのと、
将来的には機械学習を導入したいのでそれを見越したdb設計ができるか・・・
その部分はジーズアカデミーを卒業した先輩やメンターの方にも少しご協力予定です。最後に
長い文章ここまで読んで頂いてありがとうございました!!
色々中途半端でまだまだ未熟な私ですが、
いつも応援し支えてくれる周囲に感謝の気持ちを忘れず、
1日でも早く現場で疲弊している看護職の業務が楽になるようなサービスを提供できるよう、
今後も日々精進したいと思います。
- 投稿日:2020-08-04T04:46:33+09:00
【Laravel6.x】オートインクリメントの主キーを後から文字列型へ変えたい
環境
PHP laravel PostgreSQL 7.4.1 6.18.31 11.8 困ったこと
Laravelはデフォルトでサロゲートキーを採用しており、
php artisan make:migration
で生成されるマイグレーションファイルの主キー(id)は初期値がauto incrementとなっています。
ここで、特定のテーブルで後からidを文字列型にしたい場合がありました。
テーブル定義変更のマイグレーションファイルを作成し、change()を使って以下のように記述したところ...public function up() { Schema::table('photos', function (Blueprint $table) { //型を変更 $table->string('id')->primary()->change(); }); }実行結果
$ Illuminate\Database\QueryException : SQLSTATE[42P16]: Invalid table definition: 7 ERROR: multiple primary keys for table "photos" are not allowed (SQL: alter table "photos" add primary key ("id"))どうやら、もともとのidとは別に文字列型のidを定義していると解釈され、「単一の主キーが複数設定されている」というエラーになるようです。
解決策
カラム定義を変更する前に、いったん既存の主キーを除去します。
public function up() { Schema::table('photos', function (Blueprint $table) { // 主キーを除去 $table->dropPrimary('id'); // ★追加 //型を変更 $table->string('id')->primary()->change(); }); }参考
「インデックス除去」の項
https://readouble.com/laravel/6.x/ja/migrations.html
- 投稿日:2020-08-04T03:31:54+09:00
Laravel Socialiteを使用してソーシャルログイン を実装する
Laravel Socialiteを使用してソーシャルログインでの登録・ログイン機能を実装していきます。
Googleの設定
GoogleAPIs
上記にアクセスして、『プロジェクトを作成』を選択する新しいプロジェクト
プロジェクト名: 適宜
場所: 組織なし
を入力して『作成』を押下Google Cloud Platform
利用規約をチェックし『同意して続行』を押下
左上ハンバーガーメニュー/『APIとサービス』/『OAUTH同意画面』を選択する
OAuth同意画面
UserType: 外部を(適宜)選択し『作成』を押下
アプリケーション名: 適宜
『保存』を押下サイドメニュー/『認証情報認証情報を作成』/『OAuthクライアントID』を選択する
OAuthクライアントIDの作成
アプリケーションの種類: 『ウェブアプリケーション』をチェック
名前:適宜
承認済みのリダイレクトURI: http://localhost/login/google/callback
『作成』を押下OAuthクライアントを作成しましたと表示されるので下記のファイルへ追記する
laravel/.envGOOGLE_CLIENT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com GOOGLE_CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxうまく動作しない場合
APP_URL=http://localhost:10080などAPP_URLを細かく指定すると動作する可能性があります。Laravel Socialiteをインストール
$ docker-compose exec workspace composer require laravel/socialiteconfigファイルを編集
laravel/config/services.php'google' => [ 'client_id' => env('GOOGLE_CLIENT_ID'), 'client_secret' => env('GOOGLE_CLIENT_SECRET'), 'redirect' => env('APP_URL') . '/login/google/callback', ],returnの中に上記を追記する
Googleへのリダイレクト処理
laravel/routes/web.phpRoute::prefix('login')->name('login.')->group(function () { Route::get('/{provider}', 'Auth\LoginController@redirectToProvider')->name('{provider}'); Route::get('/{provider}/callback', 'Auth\LoginController@handleProviderCallback')->name('{provider}.callback'); }); Route::prefix('register')->name('register.')->group(function () { Route::get('/{provider}', 'Auth\RegisterController@showProviderUserRegistrationForm')->name('{provider}'); Route::post('/{provider}', 'Auth\RegisterController@registerProviderUser')->name('{provider}'); });ログインコントローラーにアクションメソッドを追加
下記をコントローラー内に追記する
laravel/app/Http/Controllers/Auth/LoginController.phpuse App\User; use App\Providers\RouteServiceProvider; use Illuminate\Foundation\Auth\AuthenticatesUsers; use Laravel\Socialite\Facades\Socialite; // 省略 public function redirectToProvider(string $provider) { return Socialite::driver($provider)->redirect(); } public function handleProviderCallback(Request $request, string $provider) { $providerUser = Socialite::driver($provider)->stateless()->user(); $user = User::where('email', $providerUser->getEmail())->first(); if ($user) { $this->guard()->login($user, true); return $this->sendLoginResponse($request); } return redirect()->route('register.{provider}', [ 'provider' => $provider, 'email' => $providerUser->getEmail(), 'token' => $providerUser->token, ]); }ログイン画面のBladeを編集
laravel/resources/views/auth/login.blade.php<a href="{{ route('login.{provider}', ['provider' => 'google']) }}" class="btn btn-block btn-danger"> <i class="fab fa-google mr-1"></i>Googleでログイン </a>ユーザー登録コントローラーにアクションメソッドを追加
下記をコントローラー内に追記する
laravel/app/Http/Controllers/Auth/RegisterController.phpuse Illuminate\Http\Request; use Laravel\Socialite\Facades\Socialite; // 省略 public function showProviderUserRegistrationForm(Request $request, string $provider) { $token = $request->token; $providerUser = Socialite::driver($provider)->userFromToken($token); return view('auth.social_register', [ 'provider' => $provider, 'email' => $providerUser->getEmail(), 'token' => $token, ]); } public function registerProviderUser(Request $request, string $provider) { $request->validate([ 'name' => ['required', 'string', 'alpha_num', 'min:3', 'max:16', 'unique:users'], 'token' => ['required', 'string'], ]); $token = $request->token; $providerUser = Socialite::driver($provider)->userFromToken($token); $user = User::create([ 'name' => $request->name, 'email' => $providerUser->getEmail(), 'password' => null, ]); $this->guard()->login($user, true); return $this->registered($request, $user) ?: redirect($this->redirectPath()); }laravel/views/auth/register.blade.php<a href="{{ route('login.{provider}', ['provider' => 'google']) }}" class="btn btn-block btn-danger"> <i class="fab fa-google mr-1"></i>Googleで登録 </a>以上でGoogleアカウントで登録・ログインができるようになりました。
- 投稿日:2020-08-04T02:20:32+09:00
Laravel + Vue.jsの導入方法
LaravelのBladeにVueコンポーネントを組み込む方法をまとめます。
環境
- laradock
- php: 7.3
- Laravel: 7.2
Vue.jsをインストールする
laravel/package.json"vue": "^2.6.11", "vue-template-compiler": "^2.6.11"$ docker-compose exec workspace npm installVueコンポーネントを作成する
試しにハートボタンを作成します。
laravel/resources/js/components/SampleLike.vue<template> <div> <button type="button" class="btn m-0 p-1 shadow-none" > <i class="fas fa-heart mr-1" /> </button> 10 </div> </template> <script> </script>app.jsを編集
laravel/resources/js/app.jsimport Vue from 'vue' import Samplelike from './components/SampleLike' const app = new Vue({ el: '#app', components: { SampleLike, } })laravelの全画面で使用できるようにここで読み込みます。
Laravel Mixを編集
laravel/webpack.mix.jsmix.js('resources/js/app.js', 'public/js') .sass('resources/sass/app.scss', 'public/css') .version();上記はresources/js/app.jsをトランスパイルしてpublic/jsのapp.jsというファイルで保存されるよというソースです。
.version()はトランスパイルされる時に毎回idを採番する役割ですが、これは同じidの古いjavascriptをブラウザキャッシュに残さないためです。.gitignoreを編集
下記はjavascriptが編集される都度トランスパイルされてファイルが作成・更新されていくため、
管理対象から外しておきます。laravel/.gitignore/node_modules /public/css # 追加 /public/hot /public/js # 追加 /public/mix-manifest.json # 追加トランスパイルの実行
$ docker-compose exec workspace npm run watch-pollDONE Compiled successfullyと表示されればトランスパイル成功です。
上記のコマンドはjavascriptが編集されたら自動でトランスパイルしてくれます。app.blade.phpを編集
laravel/resources/views/app.blade.php{{--省略--}} <body> <div id="app"> {{--追加--}} @yield('content') </div> {{--追加--}} <script src="{{ mix('js/app.js') }}"></script> {{--追加--}} {{--省略--}} </body>BladeにVueコンポーネントを組み込む
laravel/resources/views/posts/index.blade.php<div class="card-body pt-0 pb-2 pl-3"> <div class="card-text"> <sample-like> </sample-like> </div> </div>組み込むときはケバブケースで記述する。
これでハートボタンとダミーの10が表示でき、Vueコンポーネントを組み込めたかと思います。
- 投稿日:2020-08-04T02:17:37+09:00
【Laravel】ルートグループを定義して、まとまり感のあるルートを作成する
ルートグループは、ミドルウェアや名前空間のようなルート属性を、一括して複数のルートに適応させる手法です。
Route::group
メソッドを使用します。指定のミドルウェアをルートグループに適応させる
グループとしてまとめられた各ルートにミドルウェアを指定した例がこちら。
routes/web.phpRoute::middleware(['first', 'second'])->group(function () { Route::get('/', function () { // firstとsecondミドルウェアを使用 }); Route::get('user/profile', function () { // firstとsecondミドルウェアを使用 }); });
Route::middleware
メソッドを使用してfirst
ミドルウェアとsecond
ミドルウェアを適応させることが記述されています。このRoute::middleware
にgroup
メソッドをチェーンする形で書いていきましょう。グループ内の各ルートにRoute::middleware
メソッドで指定したミドルウェアが適応されます。このグループ内の各ルートは、
first
ミドルウェア、second
ミドルウェアの順に実行されます。実行される順はRoute::middleware
メソッドに指定した配列の順序となります。