20200531のlaravelに関する記事は6件です。

かんたんLaravel + Vue.jsでVueUIを使用してログイン、登録の実装

LaravelにはwebpackのようなLaravel-Mixがあり、それを使うことによりLaravel上で
Vue.jsが実装できます。
今回は、いくつかのコマンドを打つことでかんたんにVueUIを使用してログイン、登録の実装します。

ターミナルにコマンドを打ち込んでいきます。

  # laravelプロジェクト作成
 laravel new 「プロジェクト名」
 #作成したプロジェクトに移動
 cd 「プロジェクト名」

npmは、Node Package Managerの略でNode.jsのパッケージ(Package)を管理する(Manager)ツールです。
インストール方法は、以下のgithubを参考してください。
https://github.com/npm/cli
ダウンロードは、以下のリンク
https://nodejs.org/en/download/

#npmをインストール
npm install
#一度コンパイルをします。
npm run dev

問題がなければVueのログイン・php登録UIをインストールします。
2回コマンドを入力しなければなりません。

#1 インストールに時間がかかります。
composer require laravel/ui
#2 1が終了後
php artisan ui  vue --auth

最後に

npm install && npm run dev

サーバーを立ち上げて確認します。

php artisan serve

完成!!!

スクリーンショット 2020-05-31 22.23.46.png
スクリーンショット 2020-05-31 22.40.41.png
スクリーンショット 2020-05-31 22.40.52.png

以下のパスにExampleComponent.vueもインストールされてます。
resources/js/components/ExampleComponent.vue
これの表示の仕方は、次回します。

bootsrapも使えるように設定されており、bootsrapを使うためにJquery,Popper.jsも入れられています。
package.jsonを確認するとわかります。
スクリーンショット 2020-05-31 22.37.36.png

PHPをすぐに始めることができるMAMP(Mac), XAMPP(Windows)があります。

MAMP
https://www.mamp.info/en/mac/
XAMPP
https://www.mamp.info/en/mac/

laravelの環境構築は、すごく大変でした。。。
MacOS違いだけでもやり方が違ったり。

僕は、Udemyを利用して環境構築をしました。
【2日でできる】はじめての PHP 7 x Laravel 6 入門
https://www.udemy.com/course/php7study/

少しでも参考になれば幸いです。

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

【PHP(Laravel)】ControllerからViewにデータを渡す2つの方法

概要

  1. ビューメソッドを使用してデータを渡すビューを指定する。
  2. データを渡す。(方法2つ)

1.ビューメソッドを使用してビューを指定する

例)articlesコントローラーのindexファイルを指定する

return view('articles.index')

2.データを渡す。(方法2つ)

データが入った変数 $articles をビューに渡す。

1.Withメソッドでデータを渡す。

return view('articles.index')->with(['articles' => $articles]);

2.Compact関数でデータを渡す。

return view('articles.index', compact('articles'));
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WSL2+Ubuntu+Docker+Laravel+MariaDB

下記の記事を参考に、動かなかった部分などを調整しながら実施。
https://qiita.com/A-Kira/items/1c55ef689c0f91420e81
https://qiita.com/ucan-lab/items/5fc1281cd8076c8ac9f4

最終的に以下のように実行してうまくいった。

開発環境のセットアップ

前提として、前回の記事を参考に実行環境を準備しておく。
Windows10+WSL2+Ubuntu+Docker

ディレクトリ・ファイル構成

以下のように、Windows側でフォルダおよびファイルを作った。

project
├── docker
│   ├── app
│   │   ├── Dockerfile
│   │   ├── php-fpm.d
│   │   │   └── zzz-www.conf
│   │   └── php.ini
│   ├── db
│   │   ├── my.cnf
│   └── nginx
│   └── default.conf
├── server
└── docker-compose.yml

docker-compose.yml
version: '3'

services:
  app:
    container_name: app
    build: ./docker/app
    volumes:
    - ./server:/var/www/html

  nginx:
    image: nginx
    container_name: nginx
    ports:
    - 80:80
    volumes:
    - ./server:/var/www/html
    - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
    - app

  db:
    image: mariadb:10.4
    container_name: db
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: laravel_db
      MYSQL_USER: laravel
      MYSQL_PASSWORD: secret
      TZ: Asia/Tokyoa
    volumes:
    - ./docker/db/data:/var/lib/mysql
    - ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf
    - ./docker/db/sql:/docker-entrypoint-initdb.d
    ports:
    - 3306:3306
app/Dockerfile
FROM php:7.4-fpm
COPY php.ini /usr/local/etc/php/

RUN apt-get update \
    && apt-get install -y \
        libfreetype6-dev \
        libjpeg62-turbo-dev \
        libpng-dev \
        libzip-dev \
        zlib1g-dev \
        unzip \
        vim \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install \
        gd \
        zip \
        pdo_mysql

ENV TZ=Asia/Tokyo \
  COMPOSER_ALLOW_SUPERUSER=1 \
  COMPOSER_HOME=/composer

COPY --from=composer /usr/bin/composer /usr/bin/composer

ENV COMPOSER_ALLOW_SUPERUSER 1

ENV COMPOSER_HOME /composer

ENV PATH $PATH:/composer/vendor/bin

WORKDIR /var/www/html
app/php-fpm.d/zzz-www.conf
[www]
listen = /var/run/php-fpm/php-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0666
app/php.ini
zend.exception_ignore_args = off
expose_php = on
max_execution_time = 30
max_input_vars = 2000
upload_max_filesize = 32M
post_max_size = 32M
memory_limit = 512M
error_reporting = E_ALL
display_errors = on
display_startup_errors = on
log_errors = on
error_log = /dev/stderr
default_charset = UTF-8

[Date]
date.timezone = ${TZ}

[mysqlnd]
mysqlnd.collect_memory_statistics = on

[Assertion]
zend.assertions = 1

[mbstring]
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"
db/my.cnf
[mysqld]
character_set_server = utf8mb4

# Error Log
log-error = mariadb_error.log

# Slow Query Log
slow_query_log = 1
slow_query_log_file = mariadb_slow.log
long_query_time = 1.0
log_queries_not_using_indexes = 0

# General Log
general_log = 1
general_log_file = mariadb_general.log

[mysql]
default-character-set = utf8mb4

[client]
default-character-set = utf8mb4
nginx/default.conf
server {
  listen 80;
  index index.php index.html;
  server_name localhost;
  error_log  /var/log/nginx/error.log;
  access_log /var/log/nginx/access.log;
  root /var/www/html/public;

  location / {
    try_files $uri $uri/ /index.php$is_args$args;
  }

  location ~ \.php$ {
    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;
  }
 }

Docker環境の起動

docker-compose up -d

# 上記完了後、appコンテナに入る
docker-compose exec app bash

Laravelのセットアップ

composer create-project "laravel/laravel=6.*" .
chmod 766 storage -R
chmod 766 bootstrap/cache -R
chown www-data:www-data storage -R
chown www-data:www-data bootstrap/cache -R
vim .env
.env
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel_db
DB_USERNAME=laravel
DB_PASSWORD=secret
php artisan config:cache
php artisan migrate

Windows側のブラウザで、http://localhost/にアクセスすると、Laravelページが表示される。これが完了。

分からなかったこと

app/Dockerfileのところで、Laravelアプリを直接インストールしようとしてエラーは出なかったけど、コンテナが起動したあと見に行ったら無かった。
以下の文を入れたらいけるかなーと思ったのだけど。
RUN composer create-project "laravel/laravel=6.18" .

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

Laravelでメモリリーク??? 実はそんなわけなかったというしょうもない話

タイトルで若干ネタバレしてますが、ほんとしょうもない話です。ただ、おそらく同様のことで悩まれている方が何人かいるようなので、記事にしてみます。最後の方にちょっとした知見もありますが、ほぼ読み物です。

ちなみにSQSキューワーカーでメモリリークが起きるという記事がQiitaにありますが、今回の記事はこの件と直接関係はありません。

参考)
https://qiita.com/sh-ogawa/items/d64cafce2a2646b7abc6

単純な処理でなぜか延々と膨れ上がるメモリ使用量

Laravel 6.xでデータベース(今回はMySQLですがこの話に関係はない)に数万行のデータをインポートしようと試みたある日のことでした。CSVファイルから1000行ずつデータを読み出して1行ずつインサートするという手抜き超簡単なプログラムです(Laravel Excelを使用)。インポートプログラムが完成して数万行あるCSVファイルを食わせてバッチを実行したところ、数千行まで処理が走った瞬間に

PHP Fatal error: Allowed memory size of xxx bytes exhausted.

「ああん? いやいや、たかが数千行でメモリ食い潰すほどのことはなかろう。てか、1000行ずつデータとってBULK INSERTすらもせずゆっくりインサートしてるのにどこでこんなにメモリなんか使ってるんだ??? ははーん・・・・、これはなんかメモリリーク的なことが起きてるのでは????」

そもそもPHPでは意図的にメモリを確保したり解放したりなんてまずしませんし、メモリリーク的なことが起きるとしても循環参照が起きるなどでかなりレアケースではありますが…。以下を参考。

【PHP7.4新機能】弱参照(WeakReference)とGCとメモリリークについて整理したよ!
https://qiita.com/miracle-FJSW/items/f35c3e90a5d14eb6eba3

なんて変に勘ぐってしまったのが事の始まりでした。

プロセスのメモリ使用量を監視してみると、確かに徐々にメモリ使用量が膨れ上がり、1分間くらいで数十MBずつくらい物理メモリ(RES)が盛り盛りと増えていくのです。これは何事か!?
image.png
4000行くらい入れただけで436MBも使っちゃってる・・・

さらっと調べてみてもどうも同様のケースは見つけられない

データを読み込んで、そのデータをDBにインサートするだけという普通のことをしているだけなので、さすがに調べたら見つかるだろうと思ったのですが、どうにも見つかりません。でてくるのは「クエリログがメモリを食い潰しているのでそれを切れ!(\DB::connection()->disableQueryLog();)」的な記事がちらほら出てくるのですが、どうもLaravel5.5時代の話のようです。
参考
Memory leak on database insert function
https://github.com/laravel/framework/issues/30012

今はデフォルト設定でそのようなことは起きない模様。

ただ、DBのインサートをする行だけコメントアウトしてプログラムを実行すると、たしかにメモリ使用量は増えないので、Eloquentあたりになにかバグでもあってそれを踏んでいるのだろうか?なんてこの時点では思ってしまいました。

Laravel Telescope の存在に気づく

こまったなぁ、と思いつつ解決できないこと数か月・・・(一時的にphp.iniの設定をいじり、メモリがっつり増やせばデータは全件入るのでめちゃくちゃ困ってるわけではなかった)。

ある日、ぼんやりとプロジェクトファイル全体を眺めていたら、Laravel Telescopeを入れていることにふと気づきました。今までまったく使ってないのになんでこんなもん入れてるんだ? なんて思いつつ、すごく嫌な予感がしました。Laravel Telescopeをご存じでない方に、説明ページの冒頭を引用させていただきます。

Laravel TelescopeはLaravelフレームワークのエレガントなデバッグアシスタントです。Telescopeはアプリケーションへ送信されたリクエスト、例外、ログエンティティ、データクエリ、キュージョブ、メール、通知、キャッシュ操作、スケジュールされたタスク、さまざまなダンプなどを提示します。TelescopeはLaravelローカル開発環境における、素晴らしいコンパニオンです。
image.png

あー、これは危険な香りがプンプンする!!!ということで、これを無効にする設定(.envにTELESCOPE_ENABLED=false)をいれてphp artisan config:cacheしたあとにスクリプトを実行すると・・・ はいビンゴでした。

君か・・・ 数か月も見つけられなかったよ・・・

Laravel Telescope の一部機能を無効にする方法は色々ある模様

上の例では機能全体を無効にしましたが、一部機能だけ無効にすることもできます。詳しくはLaravel Telescopeのドキュメントを見ていただくといいと思いますが、今回の場合だと、Queryワッチャーをオフにすればメモリの使用量は大幅に減ります。ただ、Queryワッチャー以外でもメモリは使用しているので、ちょろちょろとメモリ使用量が増えてはいきます。

コード内の一部のみLaravel Telescopeを無効にしたい場合は

use Laravel\Telescope\Telescope;

//〜略〜

Telescope::stopRecording();
//Laravel Telescopeでメモリ食いの処理
Telescope::startRecording();

という感じで書けばメモリ問題も上手く捌けるようです。

参考)
Query builder memory leak on large insert
https://github.com/laravel/framework/issues/27539

この記事はLaravel Telescopeの件で気づいた後に見つけたけど、やっぱりメモリリークって勘違いするよなぁw

結論

Laravel Telescopeはメモリ食うから気をつけろ。

そして、入れたことを忘れるな(普通は忘れないよねw)

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

Laravelでメール送信する

前提条件

eclipseでLaravel開発環境を構築する。デバッグでブレークポイントをつけて止める。(WindowsもVagrantもdockerも)
本記事は上記が完了している前提で書かれています
プロジェクトの作成もapacheの設定も上記で行っています

Gmailのアプリパスワード取得

今回はLaravelからGmailを使ってメールを送信しようと思います
そのためにGmailのアプリパスワードを取得します

(1) googleアカウントにアクセス
(2) セキュリティをクリックし2段階認証プロセスをONにする
a.png

(3) セキュリティをクリックしアプリパスワードをクリックする
b.png

(4) パスワードの取得
アプリを選択→メール
デバイスを選択→その他(名前入力) 適当な名前を入力する
生成をクリック

表示されたパスワードをメモしておく

SMTPサーバの情報を設定

/sample/.envを編集

‥‥
MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=XXXXX@gmail.com
MAIL_PASSWORD=XXXXXXXXXX
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=XXXXX@gmail.com
MAIL_FROM_NAME="sample sender"
‥‥

MAIL_USERNAME、MAIL_FROM_ADDRESSは送信元のGmailアドレス
MAIL_FROM_NAMEは送信者名
MAIL_PASSWORDは先ほど取得したアプリパスワード(半角スペースはいらない)

ここで設定した値は/sample/config/mail.phpで使われます

Mailableクラス作成

(1)コマンドラインで
cd sample
php artisan make:mail SampleMail
xdebugの設定をしているとeclipseが実行していいですかというプロンプトを出すのでOKを押します
eclipseプロジェクトを右クリック→リフレッシュ
/sample/app/Mail/SampleMail.phpが現れます

(2) SampleMail.php修正

SampleMail.php
<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class SampleMail extends Mailable
{
    use Queueable, SerializesModels;

    public $sample;
    private $imgName;
    private $imgMineType;
    private $imgData;

    public function __construct($sample, $imgName, $imgMineType, $imgData)
    {
        $this->sample = $sample;
        $this->imgName = $imgName;
        $this->imgMineType = $imgMineType;
        $this->imgData = $imgData;
    }

    public function build()
    {

        return $this->view('sample.mailContentHtml')
                     ->text('sample.mailContentText')
                     ->subject('sample mail')
                     ->attachData(
                         $this->imgData,
                         $this->imgName,
                         [
                         'mime' => $this->imgMineType,
                         ]);
    }
}

変数宣言$sample$imgName$imgMineType$imgDataを追記
public変数はメール本文のview内で使用できるようになります
コンストラクタを変数受け取れるように修正
buildメソッド実装
viewはメール本文HTML用。後でmailContentHtml.blade.phpを作成します
textはメール本文HTML用。後でmailContentText.blade.phpを作成します
subjectはメールタイトル
attachDataは添付ファイル

Controllerにメソッド追加

(1) /sample/app/Http/Controllers/SampleController.phpに下記を追記
use App\Mail\SampleMail;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Storage;

(2) /sample/app/Http/Controllers/SampleController.phpにmailメソッドを追記

    public function mail()
    {
        $stream = Storage::readStream('sample.png');
        $imgData = stream_get_contents($stream);
        fclose($stream);

        Mail::to("XXXXXXXXXXXXXXXX@gmail.com")
            ->cc("XXXXXXXXXXXXXXX@gmail.com")
            ->bcc("XXXXXXXXXXXXXXXXX@gmail.com")
            ->send(new SampleMail('sample text', 'sample.png', 'image/png', $imgData));

        return view('sample.mail');
    }

Storageクラスは/sample/storage/app配下のファイルを扱えるクラス。どのフォルダを扱えるようにするかは、/sample/config/filesystems.phpで設定されている
Storage::readStream('sample.png')で/sample/storage/app/sample.pngのリソースを取得している
toは送信先
ccはカーボンコピー
bccはブラインドカーボンコピー
sendで先ほど作成したMailableクラスを指定

(3) サンプル用の添付ファイル
適当な画像作成ソフトでsample.pngを作成し、/sample/storage/app/sample.pngに保存

(4) /sample/routes/web.phpに下記を追記
Route::get('sample/mail', 'SampleController@mail');

viewの作成

(1) /sample/resources/views/sample/mail.blade.phpファイル作成

mail.blade.php
<html>
    <head>
        <title>sample</title>
    </head>
    <body>
        メール送信しました
    </body>
</html>

(2) /sample/resources/views/sample/mailContentHtml.blade.phpファイル作成

mailContentHtml.blade.php
<html>
    <body>
        <div style="font-weight: bold; color: red;">{{ $sample }}</div>
    </body>
</html>

(3) /sample/resources/views/sample/mailContentText.blade.phpファイル作成

mailContentText.blade.php
{{ $sample }}

Mailableクラスのpublic変数sampleを出力しています。
Mailableクラスのpublic変数はメール本文のviewで使うことができます

動作確認

http://localhost/laravelSample/sample/mail

メール送信しました

メールが送信され受信できました

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

Laravelとjsのfetchの組み合わせで躓いた話

何が起きたか

jsでajax通信がしたく以下のように書いた。

fetch(url, {
  method: "POST",
  headers: { "Content-Type": "application/json; charset=utf-8" },
  body: JSON.stringify(parameters)
})

これで、バリデーションエラーで弾かれた場合、Laravelからはステータスコード422とエラーメッセージが帰ってくるはずだった。
なのに、ステータスコードは405でしかもエラーメッセージは何も帰ってこない。
これの解決に3時間くらいかかってしまったのでここに残しておく。

結論

headersには"X-Requested-With": "XMLHttpRequest"が必要。

解説

結論を見れば分かるかもしれないが、Laravel(正確には拡張元のsymfony)はリクエストヘッダーの上記を見てajaxかどうかを判断している。
なのでこれを入れないと、Laravelは通常のリクエストと判断しフォーム画面に戻すべくRedirectResponseを返す。
これにより、何等かの原因で405というおかしなコードが帰ってきた(この時点でおかしいことは分かったのでこれ以上は詳しくは見ていない)。

実際にソースを追ってみたところ以下のようになっている。

  1. まずここで、バリデーションに引っ掛かった場合はfailedValidation()を実行しValidationExceptionをthrow
  2. 例外ハンドラがValidationExceptionをcatchし、ここでJsonResponseを返すかRedirectResponseを返すかを分岐
  3. expectsJson()ここajax()の結果からajax通信かどうかを見ており
  4. ajax()ここでxmlHttpRequestかを見ており
  5. xmlHttpRequestかはここ"X-Requested-With": "XMLHttpRequest"かを見ている

所感

「laravel fetch 405」とかでググってもヒットしないものだから苦労した。。常識なのだろうか。
常識なのであればこの機会に知ってよかったと思うことにする。

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