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

Serverless Laravel を振り返る※お金のお話もあるよ!

AWS Lambda x Laravel でサーバーレス構築 ⇒ 本番リリースまで実施しました。

ベストプラクティスではなかったり、情報を見落としていたりもあると思いますが、
後々の Serverless Laraveler のために『こんな感じでしたよ』というのを残しておきます。

あと費用感。とても大切。

想定される読者像

  • AWS 完全に理解した!って人。
  • Laravel で Serverless したい人。
  • Serverless は理解しているけど『実際の費用感どうなん?』と思っている人。

背景とお気持ち

  • 情報公開時にアクセス/トランザクションがスパイクするようなWEBサービスを作る
  • 小規模開発なので予算は可能な限り抑えたい
  • でも開発環境で本番環境と同等の検証ができるようにしたい
  • あと開発環境をわざわざ Start / Stop するようなものは作りたくない
  • 本番環境は可能な限り自動的にスケールしてほしい
  • 最近の Lambda は VPC でも早くて、PHP もいけて、Laravel も動くらしい
  • 僕は Laravel が好き

⇒これは AWS で Laravel Serverless するしかない! やろう!!!

アーキテクチャ

基本的には下記の AWS 公式の記事のようにしました。
サーバーレス LAMP スタック – Part 4: サーバーレス Laravel アプリの構築

異なる点や補足等は以下の通り。

  • Lambda は VPC 内で動かす。

  • API Gateway の手前には CloudFront を通していない

  • DB には Aurora Serverless を採用。
    また、開発環境のみ一定時間アクセスがないとDBを止めるように設定。

  • セッション管理で ElastiCache(Redis) を入れた。

  • SES からメールを送るために SMTP インターフェース用の VPC endpoint を引いている。

  • デプロイ作業や SSH トンネル用に、EC2 インスタンスがある。

ここ好き!ポイント

本番環境同等の検証ができる

それだけ。でも、とても嬉しい。

Aurora Serverless でDBがスケーリングする

  • 開発環境:使うのは検証用の週1ぐらい、使うときには本番環境同等の検証がしたい
  • 本番環境:ユーザースパイクに合わせてDB性能も勝手にスケールして欲しい

というところを叶えてくれるポイントになった Aurora Serverless

取り分け良いのが、一定時間アクセスがないと自動的に停止する機能で、
停止時には稼働料金が掛からなくなる。ありがてぇ。
※停止後にアクセスすると1分ぐらい起動に時間は掛かるが、自動的に起動する。
※もちろん、本番環境は停止させない設定にできる

Lambda がとにかく安い

Google Analytics でピーク時 DAU 1500 人の利用があったが、
それでも無料利用枠の範囲内に収まったので $ 0.00 / month になっている。

困ったこと

セッション管理が Cookie だと Cookie が無限増殖してクライアントがこける

決済用の外部サイトに飛んで戻ってを繰り返すと、
Cookie が無限増殖してクライアントがこける
ElastiCache(Redis) の単一ノードでセッション管理して対応。

$20.0 / month。苦い。
スケールしないし、単一障害点にもなってしまった。超苦い。

Lambda が VPC 内にいるのでネットに出られない

セキュリティが担保されたり VPC 内 RDS や ElastiCache にアクセスできたりと恩恵はあるが、
AWS SES で Laravel の MAIL_DRIVER='ses' でメール送信できない、という悲しみ。
対応として、VPC endpoint から SMTP インターフェースでメール送信できるようにした。

$10.0 / month。苦い。

※NAT Gateway か NAT インスタンスで対応はできるらしい。
 が、NAT Gateway が $60.0/month になりそうだったり、そもそも管理対象を増やしたくなかったので見送り。

X-Ray が使えなかった

そもそも PHP だと使えないみたいだった。しょんぼり。

気にしていたけど杞憂だったこと

ElastiCache のサイジング

スケールせず単一障害点になってしまったので、メモリ容量を懸念。

Google Analytics でピーク時 DAU 1500 人ぐらい。
ビビって t3.small にしていたがメモリ使用率 1% にも満たなかったので t3.micro でも数千/数万は捌けそう。
※その際は NW 速度がボトルネックになるかも

Aurora Serverless のサイジング

勝手にスケールするので、料金を懸念。

Google Analytics でピーク時 DAU 1500 人ぐらい。
MySQL の FOR UPDATE ロックが絡むような処理もそこそこあったが、
最後まで1番小さいサイズ( 1 ACU で t3.medium より安い)で稼働できていた。

費用感

だいたいのね。

これが見たかったんでしょう?

開発環境

Total: $60.0 / month

  • ElastiCache(t3.micro) $20.0
  • RDS(Aurora Serverless) $15.0
  • EC2(t3.micro) $15.0
  • VPC endpoint $10.0

本番環境

Total: $120.0 / month

  • RDS(Aurora Serverless) $70.0
  • ElastiCache(t3.micro) $20.0
  • EC2(t3.micro) $15.0
  • VPC endpoint $10.0
  • CloudFront $5.0

まとめない

以上。

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

Docker X Laravel X ngrok ローカル環境を一時的に外部へ公開する

仕事で使うかな?と思って導入したら結局使わなかったので投稿して供養します。。

ngrok とは

https://ngrok.com

localhostで動いているサーバーを外部(LAN外)からアクセスできるようにリレーしてくれるツールです。

無料で使用できます。

docker-compose.yml
services:
  # ...

  ngrok:
    image: wernight/ngrok
    ports:
      - ${WEB_PORT:-4040}:4040
    environment:
      NGROK_AUTH: ${NGROK_AUTH}
      NGROK_PROTOCOL: http
      NGROK_PORT: web:80
      # SSLの場合
      # NGROK_PROTOCOL: https
      # NGROK_PORT: web:443

https://dashboard.ngrok.com/get-started/setup
サインインして authtoken を取得します。

.env

NGROK_AUTH=hogehogehogehogehoge

ちなみにサインインなしだとセッションが2時間までになります。

$ docker-compose up -d

http://localhost:4040

表示されているURLをクリックすると確認できます。

ScreenShot 2021-01-27 20.35.25.png

表示されるURLをクリックすると...

ScreenShot 2021-01-27 20.36.05.png

LaravelのWelcome画面が表示されました!

IMG_6801.PNG

外部のPCやスマホからアクセスできてるのでokです!
また、コンテナを破棄すれば接続できなくなります。(まぁ当たり前ですが...)

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

Docker × Laravel × ngrok ローカル環境を一時的に外部へ公開する

仕事で使うかな?と思って導入したら結局使わなかったので投稿して供養します。。

ngrok とは

https://ngrok.com

localhostで動いているサーバーを外部(LAN外)からアクセスできるようにリレーしてくれるツールです。

無料で使用できます。

環境

  • PHP: 8.0.1
  • Laravel: 8.23.1

Docker X Laravelとは

Docker Composeを使用してシンプルなLaravelのローカル開発環境を構築するツールです。

導入

docker-compose.yml
services:
  # ...

  ngrok:
    image: wernight/ngrok
    ports:
      - ${WEB_PORT:-4040}:4040
    environment:
      NGROK_AUTH: ${NGROK_AUTH}
      NGROK_PROTOCOL: http
      NGROK_PORT: web:80
      # SSLの場合
      # NGROK_PROTOCOL: https
      # NGROK_PORT: web:443

https://dashboard.ngrok.com/get-started/setup
サインインして authtoken を取得します。

.env

NGROK_AUTH=hogehogehogehogehoge

ちなみにサインインなしだとセッションが2時間までになります。

$ docker-compose up -d

http://localhost:4040

表示されているURLをクリックすると確認できます。

ScreenShot 2021-01-27 20.35.25.png

表示されるURLをクリックすると...

ScreenShot 2021-01-27 20.36.05.png

LaravelのWelcome画面が表示されました!

IMG_6801.PNG

外部のPCやスマホからアクセスできてるのでokです!
また、コンテナを破棄すれば接続できなくなります。(まぁ当たり前ですが...)

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

laravel 認証機能でログイン後のリダイレクト先を変更する

はじめに

laravelで認証機能をmake:authで作成する際にリダイレクト先が設定されています。また、middlewareでログインしないと任意のページに遷移できないように設定済です。
今後新たなwebアプリケーションを作成する可能性が高いので任意のページを変更してみたいと思います。

やってみること

ログインすると任意のページにリダイレクトを設定する

投稿者の環境

MacBook Pro (13-inch, 2019, Two Thunderbolt 3 ports)
macOS Big Sur バージョン11.0.1
PHP 7.3.23
Laravel Framework 6.20.7

リダイレクト先を変更してみよう

ステップ1

HTTP->Middleware->RedirectIfAuthenticated.phpを編集する。
フォルダの構成はこのようになっている。“スクリーンショット” 2021-01-27 18.12.25.jpg

RedirectIfAuthenticated.php
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;

class RedirectIfAuthenticated
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string|null  $guard
     * @return mixed
     */
    public function handle($request, Closure $next, $guard = null)
    {
        if (Auth::guard($guard)->check()) {
            return redirect('/home'); //こちらを変更する
        }

        return $next($request);
    }
}

コードの編集

RedirectIfAuthenticated.php
return redirect('/home');
//以下のように変更する
return redirect('online_reviews/hospital_list/index');

ステップ2

Authフォルダ->LoginController.phpを編集する。

LoginController.php
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = '/home';//ここを編集する。

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }
}

コードの編集

LoginController.php
protected $redirectTo = '/home';
//以下のように変更する
protected $redirectTo = 'online_reviews/hospital_list/index';

以上でコードの編集は終了です。無事にリダレクト先が変更されましたか?

解説

ルーティングの設定でweb.phpを見てみます。一番上に記述しているgroup'prefix'をしているため'online_reviews'を記述する必要がありません。その反面、リダイレクト先を設定するにはこの記述を記述しないとエラーが発生します。
groupとprefixに関してはこちらのページを参考にして下さい。

web.php
Route::group(['prefix' => 'online_reviews','middleware' => 'auth'], function(){
  Route::get('hospital_list/index','OnlineReviewsController@index')->name('online_reviews.hospital_list'); 
 //以下省略

最後に

初めての試みだったので試行錯誤の連続・・・
認証機能は自動で作成できる反面、カスタマイズが難しい・・・
ログイン機能をもっと充実させるようにがんばります!!

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

【Dcoker・Laravel】エラー対処法 Fatal error: Composer detected issues in your platform: Your Composer dependencies require a PHP version

DockerでLaravelを起動した際に、以下のエラーが発生した時の対処法。

Fatal error: Composer detected issues in your platform: Your Composer dependencies require a PHP version ">= 7.3.0". You are running 7.2.34. in /var/www/vendor/composer/platform_check.php on line 24

Composerを使うために必要なPHPのバージョンが7.3.0以上である必要があるのに、低すぎるというエラー。

PHPのバージョンを上げればいい。

問題のDockerfile

ベースイメージにphpの7.2を指定してある。

Dockerfile
FROM php:7.2-fpm

# Copy composer.lock and composer.json
COPY composer.lock composer.json /var/www/

# Set working directory
WORKDIR /var/www

# Install dependencies
RUN apt-get update && apt-get install -y \
    build-essential \
    libpng-dev \
    libjpeg62-turbo-dev \
    libfreetype6-dev \
    locales \
    zip \
    jpegoptim optipng pngquant gifsicle \
    vim \
    unzip \
    git \
    curl

# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*

# Install extensions
RUN docker-php-ext-install pdo_mysql mbstring zip exif pcntl
RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/
RUN docker-php-ext-install gd

# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# Add user for laravel application
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www

# Copy existing application directory contents
COPY . /var/www

# Copy existing application directory permissions
COPY --chown=www:www . /var/www

# Change current user to www
USER www

# Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]

対応方法

  1. ベースイメージのバージョンを上げる。(FROM php:7.3-fpm)
  2. バンドルでlibonig-devとlibzip-devを追加。(apt-get install -yのところ)
  3. エクステンションのmbstringを削除(libonigが代替する)

修正後のDockerfile

Dockerfile
FROM php:7.3-fpm

# Copy composer.lock and composer.json
COPY composer.lock composer.json /var/www/

# Set working directory
WORKDIR /var/www

# Install dependencies
RUN apt-get update && apt-get install -y \
    build-essential \
    libpng-dev \
    libjpeg62-turbo-dev \
    libfreetype6-dev \
    locales \
    zip \
    jpegoptim optipng pngquant gifsicle \
    vim \
    unzip \
    git \
    curl \
    libonig-dev \
    libzip-dev

# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*

# Install extensions
RUN docker-php-ext-install pdo_mysql zip exif pcntl
RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/
RUN docker-php-ext-install gd

# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# Add user for laravel application
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www

# Copy existing application directory contents
COPY . /var/www

# Copy existing application directory permissions
COPY --chown=www:www . /var/www

# Change current user to www
USER www

# Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]

以上で完了。


PHPのバージョンがcomposerよりも高い場合。

上記はPHPのバージョンが指定よりも低かったために発生したエラー。

仮に、PHPのバージョンが高すぎてダウングレードを要求された場合、ダウングレードせずとも、composerの設定ファイルを書き換えることで対応できる。(らしい)

対応方法

composer.jsonのconfigに以下を追加

    "config": {
        (省略)
        "platform-check": false
    },

これのみ。
以上で、エラーを拾っていた機能をOFFにできる。


(補足)エラーを実行している処理

ちなみに、エラーを拾っている処理が書かれているのは、vendor/composer/platform_check.php

image.png

platform_check.php
<?php

// platform_check.php @generated by Composer

$issues = array();

if (!(PHP_VERSION_ID >= 70300)) {
    $issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.0". You are running ' . PHP_VERSION . '.';
}

if ($issues) {
    if (!headers_sent()) {
        header('HTTP/1.1 500 Internal Server Error');
    }
    if (!ini_get('display_errors')) {
        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
            fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
        } elseif (!headers_sent()) {
            echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
        }
    }
    trigger_error(
        'Composer detected issues in your platform: ' . implode(' ', $issues),
        E_USER_ERROR
    );
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LaravelでWebアプリを作ってみた

はじめに

ドットインストールからプログラミングをはじめ、PHP,Laravelを半年ほど勉強したので何か有益なものを作ってみたいという気持ちが生まれてきました。

以前作った有益でないもの。

  • 「Ohanatter」

http://ohanatter.herokuapp.com/login

遊び方はGithubのREADMEを見てください。
https://github.com/kk0055/Ohanatter

  • ペット掲示板

https://dry-journey-16818.herokuapp.com/

これらはこれらでかわいくて好きだったのですが、もう1段階有益なものを目指しました。

有益かどうかはわかりませんが、引っ越しを考えていたので「そうだ、いらないものを人にあげるアプリを作ってみよう」という考えです。

トータル3週間くらいで完成。

「Kasih」です。
https://kasihkasih.net/

アプリの概要

不要なモノを投稿して、それを欲しい人がいたらチャットが送れる。そんなサービス。
メルカリ、ジモティー、Carousellなどを参考にしてつくりました。
AWS,Herokuは以前使ったことがあるので今回、サーバーはさくらのレンタルサーバーを使いました。初めてのレンタルサーバーはかなり詰まりましたね。。。

機能

  • 新規登録、ログイン
  • TwitterOAuthログイン(今は止めてます)
  • 投稿
  • チャット
  • チャットを受けとったときのメール通知
  • ユーザーごとの商品画面
  • カテゴリーごとの商品画面
  • 登録なしでも閲覧は可能。投稿、チャットはログイン必須

ER図

初めて書いたので難しかった。

ER_trim.png

苦労した点

  • チャット機能

アイテムごとにチャット送れるした方がいいとは思ったのですが、同じ二人のユーザー同士なら一つのメッセージボックスの中で完結できるようにしました。
どちらがいいのかわからず迷って何度かやり直しをしました。
今後、必要だと思ったら修正していきます。※必要だと思う。

  • モデルバインディング

今となってはなぜうまくいかないのかわかるのですが、しっかりと理解できておらず苦労しました。ググるうちに少しずつ少しずつ理解しました。
この時どうしてもわからずteratailで質問したところ、あっさりとヒントをもらえて、これからは何日か考えてもわからないときは聞こうと決めましたね。
すぐに聞いたら、ググったりドキュメントを見ないのである程度は自分で調べる癖は持っておきたいと思います。

  • DBまわり

リレーションがなんとなくしかわかっていなかったことを痛感させられました。
モデルのインスタンスを取っているのか、コレクションをとっているのかという考えすらなくなんとなくで書いていたら上手くいかず。

これまでは書いて試してみるというスタイルだったのですが、やはり勘ではうまくいかない。理解してないと修正もできない。
ドキュメント、Stack Overflowを何回も何回も見て焦らず理解した上で心がけるようになりました。コードだけ流し見しがちですがしっかり説明を読むことが大事。

https://readouble.com/laravel/8.x/ja/eloquent.html

また、SQLをもう一度しっかり勉強しないといけないなとも感じました。
おそらくSQLを理解していればリレーションそんなに難しくないはず。

  • フロントエンド

あまりCSSは勉強してこなかったので、主にTailwindをつかってデザインしました。Tailwindは使いやすくてすきなのですが細かい修正が難しいなと思います。
基本的にはググってよさげなデザインをコピペして、細かい部分を修正。

  • レンタルサーバ

わりとすべてが謎。なぜサーバ会社は細かいドキュメントを持っていないのか?なぜ人のブログ記事ばかりなのか?書いてることもばらばらだし。
もう理解できたので次は上手くできると思います。
ざっくりと。

Laravelドキュメントのインストーレーションより

Laravelをインストールできたら、Webサーバのドキュメント/Webルートがpublicディレクトリになるように設定してください。

Laravelのプロジェクトpublicのシンボリックリンクを公開フォルダ内に貼ればOK.
そして

コントロールパネル
→ドメイン/SSL
→ドメイン/SSL
→「WEB公開フォルダ」
をLaravelプロジェクト/publicに変更

Screenshot (507).png

結論

なにか特定の教材を参考にするのではなくググりながら書くということを意識して今回作ってみましたが、めちゃくちゃ楽しいしかなり学べる事、吸収できることが多いなと思いました。100倍くらい。

チュートリアルをやるだけだと、学べることも多いのですが基本的にはエラーも出ずすんなり進んでいくのであまり記憶に定着しないなと思います。

苦しんで苦しんで考えてる時が一番成長につながるのかな。

「Kasih」です。
https://kasihkasih.net/

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

【Laravel・Docker】コード変更してないのにWorning:require()、Fatal error:require()が出た

Dockerをよく理解できていないために今回のエラーが起きました。
このおかげで少し理解できたので備忘録のため記事にします。

さてコード書くぞ、アプリ立ち上げるぞと思ったら

スクリーンショット 2021-01-27 13.23.46.png

え...
昨日までできてたのに?
コード何もいじってないのに?
なんで?

と泣きそうでした。

いや、そういえばGitHubDeskTopで管理したいからリモートリポジトリからローカルにcloneしたな

最初はリモートだけで管理してたんですけど
ブランチとかコメントとかGUIで手軽に操作したいからこのやり方でcloneしたのです。

そうしたらローカルのディレクトリがが2つになってしまったのでcloneした方ではない方を削除したのです。
つまりこのcloneした段階ではエラーにある通りのファイルが存在しないというエラーでした。

解決方法

またこちらの神記事参考にしました。
お世話になりすぎ...

ターミナル
docker-compose exec app bash

上記コマンドでターミナルに入り

コンテナ
composer install

コンテナ内で上記コマンドをうちます。

これだけだと500 | Server Errorとなるので

コンテナ
cp .env.example .env

上記コマンドでenvの環境変数を.env.exampleを元にコピーします。

コンテナ
php artisan key:generate

上記コマンドでアプリケーションキーを生成します。

コンテナ
php artisan migrate

最後に上記のコマンドでマイグレーションして成功すれば無事に元に戻りました。

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

laravel 「Call to a member function メソッド名 on null」というエラーが出た

目的

  • 「Call to a member function メソッド名() on null」というエラーが出たので筆者の場合の解決方法をまとめる

環境

  • ハードウェア環境
項目 情報
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.11 Homebrewを用いてこちらの方法で導入→Mac HomebrewでPHPをインストールする
Laravel バージョン 6.X commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う
MySQLバージョン 8.0.21 for osx10.15 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする

エラー

  • 下記のエラーがブラウザとログに出力された。

    Call to a member function メソッド名() on null 
    
  • このエラーはクラス名->メソッド名()と記載しメソッドを呼び出している部分のクラス名部分がnullであり「saveFile()なんてメソッド無いですよ」という時に出力されるエラーである。

具体的なソースとエラー

  • エラーの出たコントローラクラスの内容を下記に記載する。

    NoticeController.php
    <?php
    
    namespace App\Http\Controllers;
    
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Mail;
    use App\Mail\AppMail;
    use App\Services\MailAttachmentService;
    
    class NoticeController extends Controller
    {
        /**
         * @var MailAttachmentService
         */
        private $mailAttachmentService;
    
        public function __construct(MailAttachmentService $mailAttachmentService)
        {
    
        }
    
        public function index()
        {
            return view('notices.index');
        }
    
        public function mailMake()
        {
            return view('notices.mails.make');
        }
    
        public function mailConfirm(Request $request)
        {
            $postData = $request->all();
    
            if (isset($postData['file'])) {
                $postData['putFileInfo'] = $this->mailAttachmentService->saveFile($postData['file']);
            }
    
            $viewData = [
                'postData' => $postData
            ];
    
            return view('notices.mails.confirm', ['viewData' => $viewData]);
        }
    
        public function mailSend(Request $request)
        {
            $postData = $request->all();
            Mail::to('test@example')->send(new AppMail($postData));
            return redirect(route('notice.index'));
        }
    }
    
  • 出力されたエラー

    Call to a member function saveFile() on null
    

悪さをしている部分

  • コントローラクラスの中のmailConfirm()メソッドの中に記載されている。$postData['putFileInfo'] = $this->mailAttachmentService->saveFile($postData['file']);でエラーが発生している。
  • このsaveFile()メソッドがnullから呼ばれていますよといったエラー内容である。
  • つまり$this->mailAttachmentServiceがnullということになるので当該メソッドにクラスを格納(依存注入)している部分を確認してみる。
  • 下記に__construct()メソッドを抜粋して記載する。

    NoticeController.php
    public function __construct(MailAttachmentService $mailAttachmentService)
    {
    
    }
    
  • __construct()メソッドの中で$this->mailAttachmentService(このクラスに新たなメソッド定義)に外部クラスを格納(依存注入)し忘れている事がわかった。(自身のクラスに新たにメソッドを定義して外部のクラスを注入することによりクラス間を疎結合にする。)

  • 下記のように修正したら正常に動作した。

    NoticeController.php
    <?php
    
    namespace App\Http\Controllers;
    
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Mail;
    use App\Mail\AppMail;
    use App\Services\MailAttachmentService;
    
    class NoticeController extends Controller
    {
        /**
         * @var MailAttachmentService
         */
        private $mailAttachmentService;
    
        public function __construct(MailAttachmentService $mailAttachmentService)
        {
            // 下記を追記
            $this->mailAttachmentService = $mailAttachmentService;
        }
    
        public function index()
        {
            return view('notices.index');
        }
    
        public function mailMake()
        {
            return view('notices.mails.make');
        }
    
        public function mailConfirm(Request $request)
        {
            $postData = $request->all();
    
            if (isset($postData['file'])) {
                $postData['putFileInfo'] = $this->mailAttachmentService->saveFile($postData['file']);
            }
    
            $viewData = [
                'postData' => $postData
            ];
    
            return view('notices.mails.confirm', ['viewData' => $viewData]);
        }
    
        public function mailSend(Request $request)
        {
            $postData = $request->all();
            Mail::to('test@example')->send(new AppMail($postData));
            return redirect(route('notice.index'));
        }
    }
    
  • 追記後に動作を確認したらエラーは出ず正常に動作した。

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