20210127のPHPに関する記事は9件です。

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で続きを読む

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では表示されない。

配列への追加と上書き

イメージしやすいように画像にしました。

PHP配列への追加と上書き_補完版.png

配列の結合や追加のために用意されている関数

  • array_merge()
  • array_merge_recursive()
  • array_push()

など、結合や追加のために用意されている関数があります。

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

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()

など、結合や追加のために用意されている関数があります。

イメージを掴んでもらいやすいように作った画像

※上でやった操作とは一部違う操作になってます。

PHP配列への追加と上書き.png

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

Mockeryでクロージャを実行する関数を使っているメソッドをテストする

例えばLaravelのトランザクションみたいなやつ

return $this->dbManager->transaction(function () {
  return some;
});

こういうコードがあるメソッドに対して、dbManagerMockeryで差し込んだとします。
その場合以下のように書くとモックできる

$mockDbManager = Mockery::mock(DatabaseManager::class);
$mockDbManager->shouldReceive('transaction')
    ->andReturnUsing(function($closure) {
        return $closure();
    });

Facade使ってたらそもそもモックの必要もないのだが、依存しているものはなるべくコンストラクタから注入したいよね!
ではまた。

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

docker-composeを使ってDocker上にLaravelを構築する方法(Nginx & php-fpm & MySQL)

docker-composeを使ってDocker上にLaravelを構築する方法。WebサーバーはNignx + php-fpmを使用。

目次

  1. Laravelをローカルに構築
  2. .envファイルの設定
  3. dockerにcomposerのデータをコピー
  4. docker-compose.ymlを作成
  5. Dockerfileの作成
  6. PHPの構成
  7. NginxとPHP-FPM
  8. Nginxの設定
  9. MySQLの設定
  10. コンテナ起動
    1. コンテナの起動状況の確認
    2. ブラウザで確認
  11. (補足)ブラウザ表示でエラーが出た場合の対処法


1. Laravelをローカルに構築する

1-1. githubからクローン

git clone https://github.com/laravel/laravel.git <プロジェクト名>


1-2. composerを使ってバンドルをインストールする。

$ composer update

composer.jsonに書いてあるバンドルがズラーっとインストールされる。

1-3 .envファイルの設定

まずは.envファイルを作成する。(.env.exampleをコピーする)

cp .env.example .env

次にキーを作成する。

$ php artisan key:generate

MySQLと接続するために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の環境を構築できる。

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 hun公式 composer image


コマンド実行例

$ 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!

ボリュームをマウントしているので、作成されたファイルがローカルに保存される。

image.png


3. docker-compose.ymlを作成する

$ vim docker-compose.yml

vimエディタでiをクリックしてinsertモードに入り、以下をコピペ。

コピペ後は、esc + :wqで保存して終了。

(参考)vimの使い方

docker-compose.yml

docker-compose.yml
version: '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 Dockerfile

vimエディタでiをクリックしてinsertモードに入り、以下をコピペ。

コピペ後は、esc + :wqで保存して終了。

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 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.ini
local.ini
upload_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.conf

vimエディタでiをクリックしてinsertモードに入り、以下をコピペ。

コピペ後は、esc + :wqで保存して終了。

app.conf
server {
    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.cnf

vimエディタで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   webserver

docker-composeのサービスで定義した、app, webserver, dbが起動している。

ブラウザで確認

localhost:80を入力するとLaravelのwelcome.blade.phpが表示される。

image.png


(補足)ブラウザ表示でエラーが出た場合の対処法

以下のようなエラーが出たら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

PHPバージョンエラー対処法



以上。

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

【PHP】while文とfor文をざっくりまとめてみた。

PHPで繰り返し処理を行おうとした時に
while文とfor文がごちゃごちゃになってしまっていたので、
備忘録としてざっくりまとめておきます。

while文

条件式が の間は、ずっと処理を繰り返します。
繰り返す回数が分からなかったり、特定のタイミングで処理を変えたい場合に便利です。
形式は以下の通りです。

初期化処理;
while (条件式) { 
 繰り返したい処理;
 更新処理;
}

実際に書いてみると以下のようになります。

$i = 1;
while ($i <= 5) {
 echo $i . "\n";
 $i = $i + 1;
}

これで、
「変数$i5以下の時、処理を繰り返してください。ちなみに$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

どちらの構文を使っても同じ処理を行えますね。
使う場面ごとに上手く使い分けていきたいものです。

参考

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

Bootstrap5のお試しと相続税計算

Bootstrap5を試してみました。

  • Bootstrap4からの移行は、3⇒4より楽そう?大きくは変わっていないような…
  • jQuery依存から脱却したのは良いと思います、そこは自由であるべきと思います
  • スターターテンプレートはこちら
  • ナビゲーションバーはこちら 、他は動かないサンプルもあるような
  • バリデーションはこちら

相続税の理解に苦しんでいるので、
Bootstrap5のお試しと↑↑の理解も兼ねて、ざっくり相続税計算を作りました。

  • このエントリーをはてなブックマークに追加
  • 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で続きを読む