- 投稿日:2021-01-27T20:40:07+09:00
Docker X Laravel X ngrok ローカル環境を一時的に外部へ公開する
仕事で使うかな?と思って導入したら結局使わなかったので投稿して供養します。。
ngrok とは
localhostで動いているサーバーを外部(LAN外)からアクセスできるようにリレーしてくれるツールです。
無料で使用できます。
docker-compose.ymlservices: # ... 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:443https://dashboard.ngrok.com/get-started/setup
サインインして authtoken を取得します。
.envNGROK_AUTH=hogehogehogehogehogeちなみにサインインなしだとセッションが2時間までになります。
$ docker-compose up -d表示されているURLをクリックすると確認できます。
表示されるURLをクリックすると...
LaravelのWelcome画面が表示されました!
外部のPCやスマホからアクセスできてるのでokです!
また、コンテナを破棄すれば接続できなくなります。(まぁ当たり前ですが...)
- 投稿日:2021-01-27T20:40:07+09:00
Docker × Laravel × ngrok ローカル環境を一時的に外部へ公開する
仕事で使うかな?と思って導入したら結局使わなかったので投稿して供養します。。
ngrok とは
localhostで動いているサーバーを外部(LAN外)からアクセスできるようにリレーしてくれるツールです。
無料で使用できます。
環境
- PHP: 8.0.1
- Laravel: 8.23.1
Docker X Laravelとは
Docker Composeを使用してシンプルなLaravelのローカル開発環境を構築するツールです。
導入
docker-compose.ymlservices: # ... 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:443https://dashboard.ngrok.com/get-started/setup
サインインして authtoken を取得します。
.envNGROK_AUTH=hogehogehogehogehogeちなみにサインインなしだとセッションが2時間までになります。
$ docker-compose up -d表示されているURLをクリックすると確認できます。
表示されるURLをクリックすると...
LaravelのWelcome画面が表示されました!
外部のPCやスマホからアクセスできてるのでokです!
また、コンテナを破棄すれば接続できなくなります。(まぁ当たり前ですが...)
- 投稿日:2021-01-27T20:09:25+09:00
PHP [ ] を使った配列への追加と上書き
簡単にまとめ書き
環境:PHP Version 7.4.13まず2次元配列を作ります。
$alphabet = array( "a", array( "b-a", "b-b", "b-c", "b-d"), "c", "d", "e"); var_dump($alphabet);var_dump()関数 に放り込んで配列の構造を表示させます。
( ↓ ブラウザの画面)array (size=5) 0 => string 'a' (length=1) 1 => array (size=4) 0 => string 'b-a' (length=3) 1 => string 'b-b' (length=3) 2 => string 'b-c' (length=3) 3 => string 'b-d' (length=3) 2 => string 'c' (length=1) 3 => string 'd' (length=1) 4 => string 'e' (length=1)echoでの表示
echo $alphabet[4];→e
echo $alphabet[1][2];→b-c
echo $alphabet;→ エラー
echo $alphabet[1];→ エラー配列はechoでは表示されない。
配列への追加と上書き
イメージしやすいように画像にしました。
配列の結合や追加のために用意されている関数
- array_merge()
- array_merge_recursive()
- array_push()
など、結合や追加のために用意されている関数があります。
- 投稿日:2021-01-27T20:09:25+09:00
PHP 配列への追加と上書き
簡単にまとめ書き
環境:PHP Version 7.4.13まず2次元配列を作ります。
$alphabet = array( "a", array( "b-a", "b-b", "b-c", "b-d"), "c", "d", "e"); var_dump($alphabet);var_dump()関数 に放り込んで配列の構造を表示させます。
( ↓ はブラウザの画面)array (size=5) 0 => string 'a' (length=1) 1 => array (size=4) 0 => string 'b-a' (length=3) 1 => string 'b-b' (length=3) 2 => string 'b-c' (length=3) 3 => string 'b-d' (length=3) 2 => string 'c' (length=1) 3 => string 'd' (length=1) 4 => string 'e' (length=1)echoでの表示
echo $alphabet[4];→e
echo $alphabet[1][2];→b-c
echo $alphabet;→ エラー
echo $alphabet[1];→ エラー配列はechoでは表示されない。
配列への追加
$alphabet[] = 100;
$alphabet[1][] = 150;array (size=6) 0 => string 'a' (length=1) 1 => array (size=5) 0 => string 'b-a' (length=3) 1 => string 'b-b' (length=3) 2 => string 'b-c' (length=3) 3 => string 'b-d' (length=3) 4 => int 150 2 => string 'c' (length=1) 3 => string 'd' (length=1) 4 => string 'e' (length=1) 5 => int 100配列への上書き
$alphabet[3] = 200;
$alphabet[1][2] = 250;array (size=5) 0 => string 'a' (length=1) 1 => array (size=4) 0 => string 'b-a' (length=3) 1 => string 'b-b' (length=3) 2 => int 250 3 => string 'b-d' (length=3) 2 => string 'c' (length=1) 3 => int 200 4 => string 'e' (length=1)2次元配列がある場所への上書き
$alphabet[1] = 300;array (size=5) 0 => string 'a' (length=1) 1 => int 300 2 => string 'c' (length=1) 3 => string 'd' (length=1) 4 => string 'e' (length=1)配列は消える。
下とほぼ同じ動作。添字を指定せずに上書き(ただの代入)
$alphabet = 400;
var_dump($alphabet);ではなにも表示されない(配列ではなくなるので)
echo $alphabet;→400おまけ:[ ] でくくり上書き
$alphabet[3] = [500];array (size=5) 0 => string 'a' (length=1) 1 => array (size=4) 0 => string 'b-a' (length=3) 1 => string 'b-b' (length=3) 2 => string 'b-c' (length=3) 3 => string 'b-d' (length=3) 2 => string 'c' (length=1) 3 => array (size=1) 0 => int 500 4 => string 'e' (length=1)意味合い的には
$alphabet[3] = array(500);と同じなので、まあそうなるか……という感じ。配列の結合や追加のために用意されている関数
- array_merge()
- array_merge_recursive()
- array_push()
など、結合や追加のために用意されている関数があります。
- 参考
イメージを掴んでもらいやすいように作った画像
※上でやった操作とは一部違う操作になってます。
- 投稿日:2021-01-27T19:03:00+09:00
Mockeryでクロージャを実行する関数を使っているメソッドをテストする
例えばLaravelのトランザクションみたいなやつ
return $this->dbManager->transaction(function () { return some; });こういうコードがあるメソッドに対して、
dbManagerをMockeryで差し込んだとします。
その場合以下のように書くとモックできる$mockDbManager = Mockery::mock(DatabaseManager::class); $mockDbManager->shouldReceive('transaction') ->andReturnUsing(function($closure) { return $closure(); });Facade使ってたらそもそもモックの必要もないのだが、依存しているものはなるべくコンストラクタから注入したいよね!
ではまた。
- 投稿日:2021-01-27T17:40:26+09:00
docker-composeを使ってDocker上にLaravelを構築する方法(Nginx & php-fpm & MySQL)
docker-composeを使ってDocker上にLaravelを構築する方法。WebサーバーはNignx + php-fpmを使用。
目次
- Laravelをローカルに構築
- .envファイルの設定
- dockerにcomposerのデータをコピー
- docker-compose.ymlを作成
- Dockerfileの作成
- PHPの構成
- NginxとPHP-FPM
- Nginxの設定
- MySQLの設定
- コンテナ起動
- (補足)ブラウザ表示でエラーが出た場合の対処法
1. Laravelをローカルに構築する
1-1. githubからクローン
git clone https://github.com/laravel/laravel.git <プロジェクト名>
1-2. composerを使ってバンドルをインストールする。
$ composer updatecomposer.jsonに書いてあるバンドルがズラーっとインストールされる。
1-3 .envファイルの設定
まずは.envファイルを作成する。(.env.exampleをコピーする)
cp .env.example .env次にキーを作成する。
$ php artisan key:generateMySQLと接続するためにDBの設定を変更する。
DB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 DB_DATABASE=laravel DB_USERNAME=root DB_PASSWORD=******DB_DATABASEとDB_PASSWORDは次で作成するdocker-composer.ymlと合わせる。
(補足)composerでプロジェクトを作成する方法
以下リンクのNo3まででローカルで動くLaravelの環境を構築できる。
2. dockerにcomposerのデータをコピー
プロジェクトのルートディレクトリに移動後、以下を実行。
$ docker run --rm -v $(pwd):/app composer install
- composerイメージからコンテナを作成しinstallを実行。
- 現在のディレクトリをコンテナ内の/appにマウント。
- コンテナ起動後にコンテナを削除する。
composerの必要なデータのみローカルの現在のディレクトリにコピーする。
バンドルが記述された
composer.lockがローカルのルートディレクトリに追加される。docker runコマンド
・
docker run [オプション] イメージ [コマンド] [引数...]--rmオプション
コンテナ終了時、自動的に削除。
composerのイメージとコンテナは不要なため。必要なデータのみマウントしたボリュームにコピーしておく。-vオプション
ボリュームのマウント。
ローカルのディレクトリをコンテナ内のディレクトリにマウントする。
--volumeの略。▼ボリュームのマウント方法
-v [ホスト側ソース:]コンテナ側送信先[:<オプション>]
- -v $(pwd):/app
- ホスト側ソースは絶対パスか、ボリューム名で指定。
- $(pwd):ホスト側の現在のディレクトリパス
- /app: コンテナ内のappディレクトリ
起動するイメージの指定
imageに
composerを指定。タグを指定していない場合はlatest。dockerはまず、localで
composer:latestを探す。なければdocker hubから指定のイメージを探す。
コマンド実行例
$ docker run --rm -v $(pwd):/app composer install Unable to find image 'composer:latest' locally latest: Pulling from library/composer 8bb409133b6b: Pull complete Digest: sha256:447516936298f9f63d0b718d1a21bd70066b6c206e174cd29938c79b8eefe7b1 Status: Downloaded newer image for composer:latest No lock file found. Updating dependencies instead of installing from lock file. Use composer update over composer install if you do not have a lock file. Loading composer repositories with package information Updating dependencies Lock file operations: 105 installs, 0 updates, 0 removals - Locking asm89/stack-cors (v2.0.2) - Locking brick/math (0.9.2) (省略) Writing lock file Installing dependencies from lock file (including require-dev) Nothing to install, update or remove 77 package suggestions were added by new dependencies, use `composer suggest` to see details. Generating optimized autoload files > Illuminate\Foundation\ComposerScripts::postAutoloadDump > @php artisan package:discover --ansi Discovered Package: facade/ignition Discovered Package: fideloper/proxy Discovered Package: fruitcake/laravel-cors Discovered Package: laravel/sail Discovered Package: laravel/tinker Discovered Package: nesbot/carbon Discovered Package: nunomaduro/collision Package manifest generated successfully. 74 packages you are using are looking for funding. Use the `composer fund` command to find out more!ボリュームをマウントしているので、作成されたファイルがローカルに保存される。
3. docker-compose.ymlを作成する
$ vim docker-compose.ymlvimエディタで
iをクリックしてinsertモードに入り、以下をコピペ。コピペ後は、
esc+:wqで保存して終了。(参考)vimの使い方
docker-compose.yml
docker-compose.ymlversion: '3' services: #PHP Service app: build: context: . #dockerfile: Dockerfile image: app_php-fpm container_name: appdocker restart: unless-stopped tty: true environment: SERVICE_NAME: app SERVICE_TAGS: dev working_dir: /var/www volumes: - ./:/var/www - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini networks: - app-network links: - webserver - db #Nginx Service webserver: image: nginx:alpine container_name: webserver restart: unless-stopped tty: true ports: - "80:80" - "443:443" volumes: - ./:/var/www - ./nginx/conf.d/:/etc/nginx/conf.d/ networks: - app-network #MySQL Service db: image: mysql:5.7.22 container_name: db restart: unless-stopped tty: true ports: - "3306:3306" environment: MYSQL_DATABASE: laravel MYSQL_ROOT_PASSWORD: password SERVICE_TAGS: dev SERVICE_NAME: mysql volumes: - dbdata:/var/lib/mysql/ - ./mysql/my.cnf:/etc/mysql/my.cnf networks: - app-network #Docker Networks networks: app-network: driver: bridge #Volumes volumes: dbdata: driver: local
4. Dockerfileの作成
$ vim Dockerfilevimエディタで
iをクリックしてinsertモードに入り、以下をコピペ。コピペ後は、
esc+:wqで保存して終了。DockerfileFROM 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 and change 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"]・
FROM php:7.2-fpm
ベースイメージにphp:7.2-fpmを指定。▼php:7.2-fpm
PHP-FPMがインストールされているDebianベースのイメージ。
5. PHPの構成
ディレクトリPHPの中にlocal.iniを作成する。
$ mkdir php $ vim php/local.inilocal.iniupload_max_filesize=40M post_max_size=40M例として、PHPの構成として、アップロードできるファイルサイズ上限を40Mに設定している。
PHPの構成が完了したら、NginxでFastCGIサーバーとしてPHP-FPMを使用するように設定する。
NginxとPHP-FPM
NignxはApachと異なりPHPを直接処理できない。このため、PHP-FPMと接続してPHPを処理できるようにする。
PHP-FPMはFast-CGI。Fast-CGIとは、WEBサーバー上でプログラムを動かすためのCGI(Common Gateway Interface)の改良版。Fastは速いの意味。
次のNginxの設定では、Fast-CGIとしてPHP-FPMを使うための設定を記述する。
6. Nginxの設定
nginx/conf.dディレクトリにapp.confファイルを作成する。
$ mkdir -p nginx/conf.d $ vim nginx/conf.d/app.confvimエディタで
iをクリックしてinsertモードに入り、以下をコピペ。コピペ後は、
esc+:wqで保存して終了。app.confserver { listen 80; index index.php index.html; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /var/www/public; location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass app:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location / { try_files $uri $uri/ /index.php?$query_string; gzip_static on; } }・
conf.d
.dはディレクトリ名であることを明示。
nginxではconf.d配下にあるすべての.confファイルを読み込む設定がされている。設定ファイルの読み込み指示例include /etc/nginx/conf.d/*.conf;・
server
httpのサーバーの設定。・
index
indexディレクティブ。URIが/で終わる場合(ディレクトリが指定されている)場合にリダイレクトするファイルを指定する。indexディレクティブの例index index.php index.html;リクエストされたURIが
/hoge/の場合に、index.phpがあれば、hoge/index.phpにリダイレクトする。ない場合はhoge/index.htmlにリダイレクトする。デフォルトは
index index.htmlとなっている。・
listen 80
listenディレクティブ。nginxサーバーが使用するポート番号に80を指定。・
error_log
エラーログを書き込むためのファイルを指定。・
access_log
アクセスログを書き込むためのファイルを指定。・
root
ドキュメントルートのディレクトリを指定する。
「/var/www/public」を指定している。・
location
特定のuriでリクエストがきた場合の処理を設定。prefixを使って指定する(完全一致や正規表現など)。指定したuriに一致したら{ }内の処理を実行する。
location <prefix> <uri> { 処理 }▼正規表現の指定
prefix 内容 なし 前方一致 = 完全一致 ~ 正規表現(大文字・小文字を区別する) ~* 正規表現(大文字・小文字を区別しない) 実例(PHP-FPMの設定)
以下はNginxをPHP-FPMに接続する設定。
location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass app:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; }正規表現で、
\.php$(末尾が.php)なら処理を実行。・try_files
指定したパスの存在確認をする。(if文に似た処理)
上記であれば、.phpにアクセスした場合は404を返す。・fastcgi_split_path_info
リクエストで渡されたURIを2分割する。
fastcgi_split_path_info ^(正規表現1)(正規表現2)$;▼正規表現1
$fastcgi_script_nameの値になる。
ここでは、(.+.php)なので、「*.php」が該当。▼正規表現2
$fastcgi_path_infoの値になる。
ここでは、(/.+)なので、*.php/以下が該当。▼実例
例えばリクエストが/show.php/article/0001の場合以下のようになる。$fastcgi_script_name=$document_root/show.php $fastcgi_path_info=article/0001・fastcgi_pass アドレス
Fast-CGIサーバーのアドレスを指定する。
・include ファイル
指定したファイルを読み込む。
ここでは設定ファイルとしてfastcgi_paramsを読み込んでいる。DebianやUbuntuの場合設定ファイルはデフォルトで/etc/nginx/fastcgi_paramsにある。
・NGINX PHP FastCGI Example・fastcgi_index ファイル
URIのパスがスラッシュ
/で終わる(ディレクトリを指定)場合に開くファイルを指定。・fastcgi_param SCRIPT_FILENAME ファイル
実行するファイル名を指定する。
$document_root$fastcgi_script_nameなので、ドキュメントルートの後に、$fastcgi_script_nameの値が続く。▼$fastcgi_script_name
fastcgi_split_path_infoの一つ目の正規表現が該当する。つまり「*.php」となり、リクエストされたURIと一致するphpファイルが実行される。fastcgi_indexとfastcgi_param SCRIPT_FILENAME
渡されたURIによって使用するphpファイルを切り替える処理になる。
fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /home/www/scripts/php$fastcgi_script_name;上記設定に対して、/page.phpが渡された場合、SCRIPT_FILENAMEが処理され、/home/www/scripts/php/page.phpが実行される。
一方、URIの終わりがスラッシュで、/page.php/の場合、fastcgi_indexが処理され、home/www/scripts/php/index.phpが実行される。
・fastcgi_param PATH_INFO
パスの情報。
ここではリクエストされたパスの.php以降の内容が入る。・(参考)Nginx http_fastgis_modules
2つ目のlocationの処理内容
location / { try_files $uri $uri/ /index.php?$query_string; gzip_static on; }リクエストされたURIが
/*(前方一致)の場合、処理を実行する。・
try_files $uri $uri/ /index.php?ファイルの存在確認をしあれば実行。なければ次のファイルの存在確認を行う。
存在確認する優先順位は、$uri,$uri/,/index.php?となる。・
gzip_static on;gzipで圧縮済みのファイル「.gz」があればそちらを配信する。
7. MySQLの設定
mysqlディレクトリの中にmy.cnfファイルを作成する。
$ mkdir mysql $ vim mysql/my.cnfvimエディタで
iをクリックしてinsertモードに入り、以下をコピペ。コピペ後は、
esc+:wqで保存して終了。app.conf[mysqld] general_log = 1 general_log_file = /var/lib/mysql/general.logここではMySQLのログの設定をしている。
・general_log
値を1(or ON)にするとログを出力する。
0(or OFF or 記述なし)の場合はログ出力をしない。・general_log_file
指定したファイルにログを出力する。
7. コンテナ起動
docker-compose.ymlのあるディレクトリで以下を実行する。
$ docker-compose up -d appサービスappを起動すれば、linkでwebserver, dbもつながっているため同時に起動する。
-dは デタッチド・モード。バックグラウンドでコンテナを実行するため、コンテナ起動後もそのターミナルでコマンドが打てる状態になる。▼(補足)サービスを指定しない場合
サービスの指定がなければ、docker-composeに記述されたすべてのサービスが起動する。コンテナの起動状況の確認
$ docker psコマンドで起動中のコンテナ一覧を表示できる。$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 04012cd50d18 mysql:5.7.22 "docker-entrypoint.s…" 6 minutes ago Up 6 minutes 3306/tcp, 0.0.0.0:3306->3306/tcp db 6d0cd9138856 app_php-fpm "docker-php-entrypoi…" 6 minutes ago Up 6 minutes 9000/tcp app f02cf8788728 nginx:alpine "/docker-entrypoint.…" 6 minutes ago Up 6 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp webserverdocker-composeのサービスで定義した、app, webserver, dbが起動している。
ブラウザで確認
localhost:80を入力するとLaravelのwelcome.blade.phpが表示される。
(補足)ブラウザ表示でエラーが出た場合の対処法
以下のようなエラーが出たらPHPのバージョンを上げ、インストールするバンドルやエクステンションを変更することで解決できる。
Fatal error: Composer detected issues in your platform: Your Composer dependencies require a PHP version ">= x.x.x". You are running y.y.y. in /var/www/vendor/composer/platform_check.php on line 24
以上。
- 投稿日:2021-01-27T16:42:28+09:00
【PHP】while文とfor文をざっくりまとめてみた。
PHPで繰り返し処理を行おうとした時に
while文とfor文がごちゃごちゃになってしまっていたので、
備忘録としてざっくりまとめておきます。while文
条件式が
真の間は、ずっと処理を繰り返します。
繰り返す回数が分からなかったり、特定のタイミングで処理を変えたい場合に便利です。
形式は以下の通りです。初期化処理; while (条件式) { 繰り返したい処理; 更新処理; }実際に書いてみると以下のようになります。
$i = 1; while ($i <= 5) { echo $i . "\n"; $i = $i + 1; }これで、
「変数$iが5以下の時、処理を繰り返してください。ちなみに$iの初期値は1ですよ。」
という繰り返し処理文の完成です。
実行結果は以下の通りです。1 2 3 4 5余談ですが、この場合に更新処理を以下のように書き換えることが可能です。
$i += 1; $i++;for文
while文と同様、条件式が
真の間は処理を繰り返します。
あらかじめ繰り返す回数が分かっている場合は、for文を使うと良いです。
形式は以下の通りです。for (初期化処理; 繰り返す条件; 更新処理) { 繰り返したい処理; }実際に書いてみましょう。
for ($i = 1; $i <= 5; $i++) { echo $i . "\n"; }この場合も出力結果は以下のようになります
1 2 3 4 5どちらの構文を使っても同じ処理を行えますね。
使う場面ごとに上手く使い分けていきたいものです。参考
- 投稿日:2021-01-27T12:59:17+09:00
Bootstrap5のお試しと相続税計算
- 投稿日:2021-01-27T09:03:01+09:00
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.phppublic 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')); } }追記後に動作を確認したらエラーは出ず正常に動作した。










