Laravel6 デフォルトのメールテンプレートを編集する
こんばんは
大したことではないけど微妙にハマったので記事にします。
Laravelは会員登録やパスワードリセットなどを通知系の機能をコマンドだけで作ることができます。
php artisan make:notification クラス名
とかで作れる気がする。詳しくは適当にぐぐって。
こんな感じのクラスが作られます。
<?php namespace App\Notifications; use Illuminate\Auth\Notifications\VerifyEmail; use Illuminate\Notifications\Messages\MailMessage; class TestVerifyEmail extends VerifyEmail { public function toMail($notifiable) { if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable); } return (new MailMessage) ->subject(Lang::get('タイトル')) ->line(Lang::get('本文1行目')) ->action( Lang::get('ボタン'), $this->verificationUrl($notifiable) ) ->line(Lang::get('本文2行目')); } }
が、
このクラスで送られるメールのテンプレがvendor配下にあって編集できない!
本文とかタイトルはこのクラスで設定できるのに!
大変だ!どうしよう!しんじゃう!!
というときに
php artisan vendor:publish --tag=laravel-notifications
というコマンドを打つとあら不思議
src/resource/vendor/notifications/email.blade.php
というファイルが生成されます。すごーい。
このファイルを適当にいじればそのままメールのテンプレートになるというわけですね。
かがくのちからってすげー!
まぁちなみに、これ公式にも載ってるんですけどね。。ググって探すより公式見た方が早い。。
(これ↓は公式ではないけど公式を訳したページなのでほぼ公式だと思ってます。)
効率的に実装する為にどうしたらいいのか思考
こんばんは。今は夜です。こんにちは。にしやまです。
実装する時、なかなか効率的に進められないのでどうしたらできるのか考えてみます。
個人的なメモ書きなので、もし見られた方がいても参考になるかはわかりませんが、、
- 実装すべきことの全体像が見えていない
- システム全体の設計を把握する
- 各所の詳細な仕様について詰められていない
- 最初にテスト仕様書や詳細設計書などを作るべき?
- どうやって実装していけばいいか手法を知らない(毎度ググってる)
- デザインパターンの勉強して実践してみる
- 実装前に動作確認仕様書を作成して実装項目を詳細まで煮詰めた方が仕様が明文化されて実装しやすくなるのではないか?
- 実装に取り掛かる前に、大まかな機能のみ挙げて、各機能を実装する前にその機能に関する動作確認仕様書(≒詳細設計)を作成する
apacheで.htaccessのphp_valueが使えない(解決編)
こんばんは。
にしやまです。
前回問題提起編として未解決の問題を記事にしてしまったわけですが、、
無事解決できたので進捗を報告いたします!
あらすじ
前回は
apache「phpのモジュールがなくて.htaccessのphp_valueがわかんないよぉ^^;」
ぼく「phpのモジュール持っとるやないかーい」
という感じでした。
原因
原因としてはphpのモジュールが読み込めていなかったことでした。
というのも、前回あげたここ
cat /etc/httpd/conf.modules.d/15-php.conf
# Cannot load both php5 and php7 modules
<IfModule !mod_php5.c>
<IfModule prefork.c>
LoadModule php7_module modules/libphp7.so
</IfModule>
</IfModule>
の<IfModule prefork.c>
というところで弾かれてphpのモジュールがロードされていませんでした。
そもそもpreforkって何
prefork
というのはapacheのMPMの種類の一つで他にはworker
とevent
というものがあります。
MPMとは
※MPMについては僕も今日初めて存在を知っていろいろググった程度の知識しかないので引用を基本とさせていただきます。
MPM は (Multi Processing Module) の略で、Webブラウザからのリクエストを Apache がどのように並行処理するか、という部分の処理をモジュール化したものです。 Apache MPMとはなんぞやという話
下はapacheの公式
- workerMPMは、多くのスレッドごとに複数の子プロセスを使用しています。各スレッドは一度に1つの接続を処理します。一般にワーカーは、prefork MPMよりもメモリフットプリントが小さいため、トラフィックの多いサーバーに適しています。
- eventMPMは、ワーカーMPMのようにねじ込まれ、より多くの要求は、スレッドをサポート新しい要求上で動作するように、メインスレッドを解放するためにいくつかの処理作業をオフに渡すことで同時に提供できるように設計されています。
- preforkMPMは、それぞれ1つのスレッドで複数の子プロセスを使用しています。各プロセスは一度に1つの接続を処理します。多くのシステムでは、preforkの速度はworkerに匹敵しますが、より多くのメモリを使用します。Preforkのスレッドレス設計は、状況によってはワーカーよりも利点があります。非スレッドセーフのサードパーティモジュールで使用でき、スレッドデバッグサポートが不十分なプラットフォームではデバッグが容易です。
Apache MPMイベント
【図解/apache】MPM prefork/worker/event の違い
なるほど。わからん。
たぶんだけど、worker, eventはCGI版用でpreforkはモジュール版用ってことかな?
workerかeventにするならphp-fpm使っとけってことだと思う。(適当)
このへんよくわかってないからまたちゃんと調べないとだね。
あと、話それるんだけど、
みたいな表記をよく見るんだけど、これはCLI版=モジュール版ってことでいいのかな?
誰か教えてください。
なぜデフォルトの設定のままなのに弾かれたのか
- centos8からdnfで降ろしてくるhttpdのデフォルトがpreforkからeventに変更された 第5章 RHEL 8.0.0 リリース
httpd -V | grep MPM
Server MPM: event
たしかにevent
になっている
デフォルトでeventになっているならそりゃphpのモジュールなんて使わないんだから読み込まないもんねえ
解決策
(今回の場合は)apacheのMPMをpreforkに変更する
vi /etc/httpd/conf.modules.d/00-mpm.conf
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so # コメントアウト外した ~中略~ #LoadModule mpm_event_module modules/mod_mpm_event.so # コメントアウト付けた
systemctl reload httpd
httpd -V | grep MPM
Server MPM: prefork
こうすることで
- apacheのMPMがpreforkになる
- phpがモジュール版としてapacheに読み込まれる
- apacheにphpが組み込まれている(=モジュール版)から.htaccess内でphp_valueが使える
- エラー解消!!!
はい、素晴らしい。
今回はモジュール版でやるからこれだけで済んだけど、
もしcgi版でphp-fpm使うでも.htaccessとかはそのまま使うよとか言われたらどうしてたんだろ。。
MPMはeventでphp-fpm使ってなんやかんやしないといけないんだよな。。大変そう。。
いや、それはもしその時が来たら考えます。
お疲れ様でした!
ここまで読んでくれてありがとうございました!
誰かのお役に立てれば幸いです。
apacheで.htaccessのphp_valueが使えない(問題提起編)
こんにちは。こんばんは。
にしやまです。
ここ2日程は仕事で本番サーバーの構築をしていたんですが、
できたーと思ってgit cloneしたら500エラーが起きてあわわわってなってます。
ので、経緯をメモとして残そうと思います。(まだ解決してない)
以下の環境で動かしています。
- CentOS8
- Apache2.4.37
- php7.3.15(cli)
ブラウザを見るとたしかにInternal Server Errorとでっかく書いてある。
なるほどね。ふむふむ。
で、apacheのエラーログを見ると
(省略)/.htaccess: Invalid command 'php_value', perhaps misspelled or defined by a module not included in the server configuration
と書いてあった。
該当の.htaccessはこんな感じです。
# Uncomment the following to prevent the httpoxy vulnerability # See: https://httpoxy.org/ #<IfModule mod_headers.c> # RequestHeader unset Proxy #</IfModule> # メモリ使用量の制限 php_value memory_limit -1 # POSTデータに許可される最大サイズ php_value post_max_size 1000M # 1つのファイルアップロードに許可される最大サイズ php_value upload_max_filesize 1000M <IfModule mod_rewrite.c> RewriteEngine on RewriteRule ^(\.well-known/.*)$ $1 [L] Rewriterule ^phpmyadmin/.*$ - [PT] RewriteRule ^$ webroot/ [L] RewriteRule (.*) webroot/$1 [L] </IfModule>
ここのphp_valueが悪さしてるんですね。
ちなみにphp_valueを全部コメントアウトしたらシステムは表示されました。
全部お前のせいだ。
などと責めてもphp_valueちゃんは解決してくれないので、
Invalid command 'php_value'
とかで適当にググってみたところ、
「phpのモジュールの読み込みが出来ていないからphp_valueが使えないんじゃねーの?」
という記事が多かったので、ちゃんとモジュールが読まれているか確認。
/etc/httpd/conf/httpd.conf 59行目
Include conf.modules.d/*.conf
ここでconf.modules.d配下の.confをすべて読み込んでいる。 なるほど。この配下にphpぽいのがあったので見てみます。
cat /etc/httpd/conf.modules.d/15-php.conf
# # PHP is an HTML-embedded scripting language which attempts to make it # easy for developers to write dynamically generated webpages. # # Cannot load both php5 and php7 modules <IfModule !mod_php5.c> <IfModule prefork.c> LoadModule php7_module modules/libphp7.so </IfModule> </IfModule>
ここでphpのモジュールを読み込んでいるのか。
中身があるのがmodules/libphp7.so
とな
cat で中身を見たらバイナリファイルがばーーーーって出てきた(小並感)(小並感って初めて使った)
あれ、、phpのモジュールあんじゃんか、、?
ってところまでわかったのでこれから他の原因を探ります。。
俺たちの冒険はまだまだこれからだ!(未完)
2020/02/23追記
解決編です!
ついでに読んでってくださいなー
VirtualBoxとVagrantを使ってコマンド1つでLAMP環境を構築させる
2度目の記事です。
先日vagrantをいろいろいじってvagrant up
だけでlamp環境を作れるようなvagrantを設定したので完全自己満で共有します。
なんでnginxじゃなくてapacheやねんって、僕も思いますけど弊社では今のところapacheの方が需要が高いから(というかまだnginx使う案件はやってなさそう)必然的にapacheになりました。が、nginx版も作ってみたいなとは思っています。
dockerの方が利便性は高そうなんだけど、弊社にはwin10home勢多くてdocker難民なのでvagrantにしました。
vagrantの使い方
動作手順
- VirtualBoxのインストール
- Vagrantのインストール
- コマンドプロンプト(win) or ターミナル(mac)を開いて
vagratn -v
を実行。インストールされていることを確認 vagrant plugin install vagrant-vbguest
を実行。共有フォルダを使うためのプラグインをインストールcd vagrant_test
(ディレクトリのダウンロード先による)このディレクトリがあるフォルダに移動。vagrant up
Vagrantfileを実行してVMを立ち上げる。(初回は時間がかかる)vagrant ssh
これで立ち上げたVMに対してssh接続できるvagrant halt
VMをシャットダウンする
構成
- CenOS7
- php7.4
- composer
- mysql8.0
- apache2.4
VirtualBox, Vagrantとは
VirtualBoxはホストOSの上にゲストOSとして新たに任意のOSを立ち上げることのできる仮想化ソフト。 VagrantはVirtualBoxの立ち上げ、設定などもろもろ自動化する為のツール。
その他
- 共有フォルダはホスト側はVagrantfileのあるディレクトリでゲスト側は/var/www/html
- DocumentRoot /var/www/html
- 実際にコードをいじる時は共有フォルダ内をいじる
- git cloneはローカル側の共有フォルダにする
vagrant ssh-config
でデフォで作られるssh設定を確認できる- composerなどのコマンドを使うときは
vagrant ssh
でVM内に入って叩く - DBクライアントにはsshで接続する
- その他vagrantコマンド
- vagrantのバージョンが最新でないと起動しないようなので注意
Vagrantfile
Vagrant.configure("2") do |config| ### # centos7をバージョン指定してインストール ### config.vm.box = "centos/7" config.vm.box_version = "1905.1" ### # HTTPのポートを設定 ### config.vm.network "forwarded_port", guest: 80, host: 8080 ### # private_networkを指定するとホストOSからのみアクセスできる ### config.vm.network "private_network", ip: "192.168.33.10" ### # 共有フォルダの設定(VagrantFileのディレクトリと/var/www/htmlを共有) ### config.vm.synced_folder ".", "/var/www/html" # ※以下はシンボリックリンクを使えるようにrsyncでやってるが調整中で動くかわからないのでコメントアウト # config.vm.synced_folder ".", "/var/www/html", type: "rsync", # rsync__exclude: ".git/", # rsync__args: ["--verbose", "--rsync-path='sudo rsync'", "--archive", "--delete", "-z", "--copy-links"] ### # ツールをvirtualboxに指定 ### config.vm.provider "virtualbox" do |vb| ### GUIは使わない vb.gui = false ### メモリは2048 vb.memory = "2048" ### シンボリックリンク作成を許可(これも調整中の為コメントアウト) # vb.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/v-root", "1"] end ### # その他のインストール項目をinstall.shから読み込む ### config.ssh.insert_key = false config.vm.provision :shell, keep_color: true, path: "install.sh" end
install.sh
# 最初にyumをupdateしておく yum update yum -y install wget zip unzip # selinux無効化 ※本来二重でやる必要はないがsedコマンドが効かなかったから二重でやってる。原因はわかっていない # ※selinux無効化は開発環境だからいいと思っているが本来はちゃんと設定などしないといけない setenforce 0 sed -i -e "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config # firewallのport開放 systemctl restart firewalld firewall-cmd --permanent --zone=public --add-service=http firewall-cmd --permanent --zone=public --add-service=https firewall-cmd --reload # php install 初期設定 yum -y install epel-release rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm yum -y install --enablerepo=remi,remi-php74 php php-fpm php-pdo php-mbstring php-gd php-json php-mysql php-xml php-pecl-zip # php.iniのバックアップ timezone設定 errorを画面に表示させる設定(開発環境のみ) cp /etc/php.ini /etc/php.ini.org sed -i -e "s/;date\.timezone =/date\.timezone = Asia\/Tokyo/g" /etc/php.ini sed -i -e "s/display_errors = Off/display_errors = On/g" /etc/php.ini # composer install EXPECTED_SIGNATURE="$(wget -q -O - https://composer.github.io/installer.sig)" php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" ACTUAL_SIGNATURE="$(php -r "echo hash_file('sha384', 'composer-setup.php');")" if [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ] then >&2 echo 'ERROR: Invalid installer signature' rm composer-setup.php exit 1 fi php composer-setup.php --quiet RESULT=$? rm composer-setup.php # どこからでもcomposerを使えるように mv composer.phar /usr/local/bin/composer # Apache起動、自動起動設定 systemctl start httpd systemctl enable httpd # httpd.confのバックアップ .htaccessの許可 cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.org sed -i -e "s/AllowOverride None/AllowOverride All/g" /etc/httpd/conf/httpd.conf # httpd.confでphpを効かせる為の設定 sed -i -e "s/DirectoryIndex index.html/DirectoryIndex index.php index.html/g" /etc/httpd/conf/httpd.conf # httpd.confの反映 systemctl reload httpd # デフォで入ってるmariadbを削除してmysql8.0をinstall yum remove mariadb-libs rm -rf /var/lib/mysql/ yum -y install http://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm yum -y install mysql-community-server mysql-community-devel mysql-utilities # my.cnfに文字コードと認証プラグインの設定(8.0では必須)を追記 sed -i -e "s/# default-authentication-plugin=mysql_native_password/default_authentication_plugin=mysql_native_password\ncharacter-set-server = utf8/g" /etc/my.cnf # mysqldの自動起動を有効化 systemctl enable mysqld systemctl restart mysqld # 変数定義 => MySQLの設定で必須 database=test_db user=db_user host_name=localhost # 初期パスワードを取得する password=`cat /var/log/mysqld.log | grep "A temporary password" | tr ' ' '\n' | tail -n1` new_password=passwordPASSWORD@999 # mysqlの初期設定 ※mysql8ではgrantコマンドでユーザーを作れない mysql -u root -p${password} --connect-expired-password -e "alter user root@localhost identified by '${new_password}'" mysql -u root -p${new_password} --connect-expired-password -e "create database $database" mysql -u root -p${new_password} --connect-expired-password -e "create user $user@$host_name identified by '$new_password'" mysql -u root -p${new_password} --connect-expired-password -e "grant all privileges on $database.* to $user@$host_name with grant option" mysql -u root -p${new_password} --connect-expired-password < /vagrant/db/database.sql
今のところはこれで動いているけどもしかしたら何かしらの問題があるかもしれない。
...ないといいなぁ。。
もっとこうした方がいいよとかあればコメントでもtwitterでも教えていただけるととてもうれしいです。
この間先輩からvagrantでやるのはOS立てるまでにして、あとの細かい設定はansibleでやった方がいいと教えてもらったのでansibleに作り替えるかもしれない。 軽く調べてみた感じansibleだと上のinstall.shをymlでもっと簡単に書けそうでよさげだった。
ファイル共有の問題点
ゲスト、ホスト間でファイル共有する時に
ゲスト側で共有ディレクトリ外に張ったシンボリックリンクをホスト側から参照できない
という問題が発生するんですが、 この問題のいい解決方法が思い浮かばないのでどなたかご教授いただきたいです。
これの解決のためにvagrantのファイル共有をrsyncの方式に変えようとしてるんだけど、 (rsyncならシンボリックリンクのファイルもリンクだけでなく元のファイルを共有できるぽい)
- ホスト→ゲストの一方しか同期されない
- vagrant
rsync-auto
というコマンドを一度叩かないと共有が始まらない - 共有フォルダ間でのシンボリックリンク作成は別途設定をするもしくはコマンドプロンプトを管理者権限で実行しないと作れない
というのがあるのでなんかいい感じにできるのないかなーーーという感じです。
この問題については引き続き検討していきます。何かいいアイデアがあれば教えてくださいな。
ばーっと書いたのでかなり雑で分かりづらい文章なきがしますが、、 ここまで読んでくださってありがとうございました。
ionicの勉強会で学んだこと
はじめて記事書きます。
以前ionicの勉強会に参加した時に会社に提出するように書いたレポートの丸コピです。
間違っている部分とかあれば教えてくださるとありがたやです。
お手柔らかにお願いします。
ionicとは
Web, iOS, androidのアプリを作ることができるクロスプラットフォームのUIフレームワーク。
Cordova/Capacitorの上にangular/react/vueがありUIをionicが担当している。
ver4からreact, vueでも使えるようになった。(2109/12/15の最新はver.4.11.7)また、根底がCordovaからCapacitorになった。 勉強会時点ではionic/vueはまだバグもあるようでおすすめは出来なさそうだった。
※2020/02/11にionic5がリリースされたようです。https://ionicframework.com/blog/announcing-ionic-5/
- Cordova/Capacitorとは何か
apache cordovaというアプリ開発用のクロスプラットフォームのフレームワークで、JS, HTML, CSSを使ってアプリ開発ができる技術。アプリに対してビルドを行う時にはCordovaが使われている。
Capacitorとはionic社がCordovaの精神をそのままに最新の技術で作り直したもの。(Cordovaが作られたのが10数年前でずっと後方互換のあるバージョンアップしかしていない為、コードの中には開発当時のものもあり最新技術で作り直したいという背景があった)
現在弊社の業務として使っているionicはangular, ionicの部分だけなので、業務上Capacitorの部分を扱うことはないがアプリ用にラップするときはCordova/Capacitorの技術を使っているので、ビルドエラーの時などはCordova/Capacitorの技術も必須になる。
逆に言えば、実はCapacitorさえあればiOS, androidのアプリを作ることができる。
ionicはどうやってネイティブにビルドしているのか
先述の通り実際にビルドしているのはionicではなくCordova/Capacitorであり、ionicはあくまでUI部分を担当している。
Cordova/CapacitorがWebアプリをWebView上で実行し、デバイス上のネイティブ機能(カメラ、GPSなど)を実行するためのインタ―フェイスを提供している。
ionicのメリット
ionicのメリットとして以下が挙げられる。
(WEB開発者にとって)学習コストの低さ
大部分のソースの統一
デフォルトでPWA対応
コミュニティが活発
- 1 について
Javascript(+ Angular, React, Vue)とHTML, CSSで開発ができるので、WEB開発者にとっては初期学習の必要なくアプリ開発を始められるので開発効率が良い。
- 2 について
OSに依存した一部機能はそれぞれの書き方をする必要があるが、その部分を除いてソースを統一できる。
その分リソースを削減できるので開発者側としては非常に大きなメリットになる。
3 について(PWA「Progressive Web Apps」とはWebサイトをネイティブアプリのように使うことができるアプリのこと)
インストールせずにアイコンをホーム画面に置ける。
プッシュ通知が利用可能となる。
キャッシュを残すのでオフラインでも閲覧可能。
読み込み速度が格段に向上する
などの利点がある。
- 4 について
Slackにionicのチームがあるようで、活発に活動していて質問などにいろいろ答えてくれることが多いらしい。また私の参加したconnpassによる勉強会も盛んでionicの開発者が直接色々話してくる。今回の勉強会では、本レポートに記述した内容の他に「ionicがCordovaをどうやってラップしているか」「circleCIによるionicの速度の継続的計測」などの話があった(レベルが高くて理解しきれずレポートには書けなかった。)
ionicのデメリット
上記の仕組みによりiOSやandroidなどのOSの違いをCordova/Capacitorが吸収してくれているが、いくつかの問題もある。
ネイティブ機能を使用できるかどうかはその為のプラグインが用意されているかどうかに依存している
OSのバージョンアップに即時対応できない。
Cordova/Capacitorが一枚かんでしまっている分どうしてもネイティブより描画速度が劣ってしまう。
- 1 について
ionicではネイティブの機能を使用できるよう各機能に対応するプラグインが用意されている。
公式によるプラグインやサードパーティ製のものなどもあるが、ざっと確認した限りでは基本的な機能はそろっている。https://ionicframework.com/jp/docs/native/overview(公式のプラグイン集)
が、すべてを網羅できているわけではないようなので、使いたいプラグインがなかった場合は諦めるか自作するなどの措置を取る必要がある。
- 2 について
Cordova/Capacitorに依存してしまっている以上、各OSがバージョンアップしてもCordova/Capacitorが新しいバージョンに対応したものを出さない限りはバージョンアップすることができない。
Cordova/Capacitorは比較的活発に動いているコミュニティではあるが、常に即時対応できるわけではない。
また、Cordova/Capacitorのバージョンアップ対応と①のプラグインのバージョンアップ対応は別の問題であるため、両方のバージョンアップ対応を待たないといけなくなる。
- 3 について
この問題は端末の性能向上とJavascriptのレンダリング速度向上によりかなり改善されているので、ゲームなどのスピードを必要とするアプリでない限りはそれほど気にならないようになっている。
とはいえ、Cordova/Capacitorが一枚噛んでいるという仕組み上、描画速度がネイティブを上回ることはない。
まとめ
今回の勉強はレベルが高く、正直何を言っているのかわからないところもそれなりにあったが、それをきっかけとしてionicのことを良く知る機会にもなったので行って正解だった。
また、このレポートを書くにあたり、勉強会のメモだけでは情報が足りなかったのでいくつかのwebサイトからも情報を集めたが、ionicについて断片的にしかもっていなかった情報をまとめることができた。
今後も機会があれば積極的に勉強会に参加していきたい。
参考サイト