- 投稿日:2019-08-29T23:17:26+09:00
さくらネットのレンタルサーバーにLaravelを導入してみた
サーバーと契約
さくらネットのHPから簡単に契約できました。
契約したら1、2分でIDとかがメールで届きました。
仮登録という件名のメールにサーバーのパスワードとか入ってました。
これを大事にメモしておく。自分のアドレスのパス
さくらネットでは(というか他もそうかもしれないが)
/home/hoge/www/
がホームディレクトリになる。
(hogeは自分のユーザー名)試しに何か転送してみる
試しに適当なindex.htmlを作成して
scp index.html hoge@hoge.sakura.ne.jp:~/www
か、FTPソフトでwww直下においてみる。
ドメイン名にもユーザー名と同じhogeがつくのでハマりやすいです。ていうか軽くハマりました。
メールちゃんとみたほうが良いです。
それで
http://www.hoge.sakura.ne.jp/index.html
にアクセスして開けたらとりあえず自分のサーバー領域は稼働しています。
apachとか自分で立ち上げなくても初めから常時起動しています。Laravelアプリを転送
本当はgitをうまく使うと楽に管理できるらしいのですが、そういうのはもっと詳しく書いている人がいるのでそちらをみてください。私もそのうちチャレンジするつもりです。
というわけで、今回はゴリ押しでアプリのフォルダごと一式全部さっきのwwwフォルダ直下にscpで送ります。
これはFTPソフトよりターミナルが楽だと思います。scp -r helloApp hoge@hoge.sakura.ne.jp:~/www
scp -r でフォルダ丸ごとコピーできます。
これで
http://hoge.sakura.ne.jp/helloApp/public/index.phpがアプリのトップページになります。
間のpublicとかなくすやり方も他のページググったら出てきます。MySQLにつなぐ
繋ぎ方はローカルサーバーより簡単だったので
やり方は他のページを見てもらうとして、
ハマったことだけ書きます。.envファイルを編集するのですが、sshでサーバーのシェルに入ってvimを使おうとしたらカーソルキーが使えなくて操作できなかった。筆者の環境がたまたまかもしれない。
ですが、さくらの管理ページから入ると専用のWEBエディタが使えてメモ帳みたいな感じで簡単に編集できました。パスワードなどが違ってDBに接続できない。
ホスト名とか必要なことが一式管理ページにあるのでそれを使えば動きました。パスワードとかがきちんと合えば、sshでアプリのフォルダにcdで入って
php artisan migration
php artisan db:seed
でローカルのDBがサーバーに再現できちゃいます。すごい。テーブル名が大文字・小文字が違って繋がらない。
マイグレーションまでできたは良いが、あるはずのテーブルがselectできないと言われた。
まさかと思いつつエラーメッセージに合わせたら動いた。
ローカルでは動いていたんだけど。
どうもMySQLはバージョンによって大文字小文字を同一視したり分けたりするらしいです。
対応は他の方が書いてくれています。
- 投稿日:2019-08-29T21:29:58+09:00
Laravel公式で紹介されているNginxの設定の理屈が分からない人向け
概要
Laravelの↓で紹介されているNginxの設定でなぜ動くのかの解説
https://readouble.com/laravel/5.8/ja/deployment.html解説
location /
部分の設定↓の部分の try_files の役割は下記の通りになっている。
- $url にファイルがあるか
- $url/(/で終わるファイルパスなので、要はディレクトリ)にディレクトリがあるか
- ↑がなければ、/index.php$query_string へ内部リダイレクトする
location / { try_files $uri $uri/ /index.php?$query_string; }
location ~ \.php$
部分の設定基本的に
location /
の結果としてindex.php
になって内部リダイレクトされている前提になる。
index.php
で内部リダイレクトされるので、location ~ \.php$
にマッチする。あとは、
location ~ \.php$
の設定に従い、php-fpmを経由してLaravelの開始スクリプトのindex.php
が実行されるという流れ。ちなみに、↓部分は、Laravelがいるサーバ(=php-fpmが起動しているサーバ)のLaravelの
index.php
のパスを指定されていれば良いので、fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;Laravelの
index.php
が/laravel/public/index.php
にいる場合、↓のようにベタ書きしても動く。fastcgi_param SCRIPT_FILENAME /laravel/public/index.php;余談1
ベタ書きした場合でも
SCRIPT_FILENAME
の末尾には$query_string
は不要
※Laravel側でちゃんとパラメータは取れる
location /
の
try_files $uri $uri/ /index.php?$query_string;
を
↓
try_files $uri $uri/ /index.php;
にするとLaravelにパラメータが来なくなる。余談2
下記の状態の場合、
リクエスト:http://localhost/aa?aaaa=123 root:/usr/share/nginx/html/
location ~ \.php$
に来た時、↓になる。$realpath_root:/usr/share/nginx/html $fastcgi_script_name:index.php $query_string:aaaa=123※
$query_string
はphp-fpmに渡す必要ないけど
- 投稿日:2019-08-29T21:15:12+09:00
Laravelメール送信機能の実装でmailtrapやGmailのSMTPサーバーを使ってみる
内容
Webアプリケーションを制作するに当たり、メール送信機能が必要であることが多々あるかと思います。
今回はLaravel5.8の環境下で、mailtrapを使用と、GmailのSMTPを使用したメール送信の2つのパターンで機能実装をしてみたので、その実装過程を纏めて投稿します。環境
macOS Mojave 10.14.6
Laravel Framework 5.8.331. SMTPサーバー
- 仮想のSMTPテストサーバーmailtrapを使って簡易的に実装
- 実際のメールアドレスを使用せず、mailtrapサイト上で内容等を確認できるため、送信機能のテストが簡易的に行える
- 開発段階で適当に入力したメールアドレスが実際に存在しても送信されることはない
- GmailのSMTPサーバーを使用して実装
- 実際にメールが送信される
2. mailtrapを使用する場合の設定
2.1 mailtrapのアカウント作成
メールアドレスで新規登録もしくは、既存のGmailやgithubアカウントも使用できる。
https://mailtrap.io/register/signup?ref=header
2.2 SMTPの情報をLaravelの設定に反映させる
2.2.1 設定値の確認
SMTP settingsの情報をenvもしくはconfig/mail.phpのどちらかに設定(念のため両方)
2.2.2 実際に設定する
上記で確認したenvもしくはconfig/mail.phpの値をそれぞれのファイルの該当部にコピペする
.envMAIL_DRIVER=smtp MAIL_HOST=smtp.mailtrap.io MAIL_PORT=2525 MAIL_USERNAME=4b5fb1796bf652 // コピペの内容のままで良い MAIL_PASSWORD=22c902aa6ac123 // コピペの内容のままで良い MAIL_FROM_ADDRESS=hoge@gmail.com // どのアドレスから送信するかを記載 MAIL_FROM_NAME=name // 名前を適当に設定上記内容をconfing/mail.phpでも同様に設定する
設定完了後は各種キャッシュクリア
$ php artisan cache:clear $ php artisan config:cache3. GmailのSMTPを使う場合の設定
GmailのSMTPを使用する場合はセキュリティの都合上、Gmailアカウントの設定変更が必要となる。
- 安全性の低いアプリ許可をオンにする方法
- 二段階認証を有効にし、アプリパスワードを発行する方法
3.1 安全性の低いアプリ許可をオンにする方法
- 安全性の低いアプリの許可をオンにする
- https://myaccount.google.com/lesssecureapps
- こちらは、二段階認証を有効にしている場合はオンにできない仕様である。すでに2段階認証が有効にされている場合は設定を解除しても良いが、下記、二段階認証有効下でアプリパスワードを発行する方法をオススメする
- .envファイルを下記の通り設定する
.envMAIL_DRIVER=smtp MAIL_HOST=smtp.gmail.com MAIL_PORT=587 MAIL_USERNAME=hoge@example.com // メールアドレスを記載(下のFROMと同じで良い) MAIL_PASSWORD=hogehogehoge // Gmailアカウントの生のパスワード MAIL_FROM_ADDRESS=hoge@example.com // どのアドレスから送信するかを記載 MAIL_FROM_NAME=name // 名前を適当に設定上記内容をconfing/mail.phpでも同様に設定する
設定完了後は各種キャッシュクリア
$ php artisan cache:clear $ php artisan config:cache3.2 二段階認証を有効にし、アプリパスワードを発行する方法
- 二段階認証の有効化
- https://myaccount.google.com/u/6/security?hl=ja
- ログインしたアカウントのGoogleアカウントページのセキュリティより二段階認証プロセスを有効にする
- アプリパスワードの発行
- 簡単に言うとenvファイルで設定するMAIL_PASSWORDに記載するパスワードを発行すること
- ログインしたアカウントのGoogleアカウントページのセキュリティよりアプリパスワードを設定する。
- アプリを選択では「メール」を選択する
- デバイスを選択では使用しているデバイスを選択する
- 設定が終わると16桁のアプリパスワードが発行されるため、それをenvファイルのMAIL_PASSWORDに記載
- 注)デプロイするアプリケーションごとに発行する必要があり、使い回しだと認証が通らないので注意。(localで使用したものをデプロイ先で使えない)
envの設定値は、「安全性の低いアプリ許可をオンにする方法」の場合と比較し、MAIL_PASSWORDの内容が異なる
.envMAIL_DRIVER=smtp MAIL_HOST=smtp.gmail.com MAIL_PORT=587 // 587にする MAIL_USERNAME=hoge@example.com // メールアドレスを記載(下のFROMと同じで良い) MAIL_PASSWORD=hogehogehoge // 発行したアプリパスワードの設定 MAIL_FROM_ADDRESS=hoge@example.com // どのアドレスから送信するかを記載 MAIL_FROM_NAME=name // 名前を適当に設定上記内容をconfing/mail.phpでも同様に設定する
設定完了後は各種キャッシュクリア
$ php artisan cache:clear $ php artisan config:cache4. Mailableクラス
設定値の入力が完了すれば、次は機能面の実装
Mailableクラスでは送信するメールの情報やその内容を設定できる4.1 Mailableクラスの作成
次のコマンドを実行すると、app/Mail/SamleMail.phpを生成される
今回はクラス名をSampleMailとする$ php artisan make:mail {クラス名} # 今回、作成するクラス名 $ php artisan make:mail SampleMail
- 生成されたapp/Mail/SampleMailのbuild()メソッドに送信するメールの送信元情報や、メールの内容を追記する
- メールの送信元や、メールの内容で状況に応じて変数を使用したい場合があるが、変数を使用する場合としない場合と2通り説明する
4.2 変数を使用せず、決まった送信元から決まった内容を送信する場合
app/Mail/SamleMail.php<?php namespace App\Mail; use Illuminate\Bus\Queueable; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; use Illuminate\Contracts\Queue\ShouldQueue; class SampleMail extends Mailable { use Queueable, SerializesModels; /** * Create a new message instance. * * @return void */ public function __construct() { // } /** * Build the message. * * @return $this */ public function build() { return $this ->from('hoge@sample.com') // 送信元 ->subject('テスト送信') // メールタイトル ->view('mail.send'); // メール本文のテンプレートとなるviewを設定 } }4.3 変数を受け取る場合
今回、下記の例では次の変数$contentをControllerから受け取ることとする
$content = ['name' => 'fuga', 'mail' => 'fuga@example.com'];
※Controller側の設定は次項で説明app/Mail/SamleMail.php<?php namespace App\Mail; use Illuminate\Bus\Queueable; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; use Illuminate\Contracts\Queue\ShouldQueue; class SampleMail extends Mailable { use Queueable, SerializesModels; /** * Create a new message instance. * * @return void */ // 引数で受け取る変数 protected $content; // コンストラクタ設定 public function __construct($content) { // 引数で受け取ったデータを変数にセット $this->content = $content; } /** * Build the message. * * @return $this */ public function build() { return $this ->from('hoge@exapmle.com') // 送信元 ->subject('テスト送信') // メールタイトル ->view('mail.send') // メール本文のテンプレート ->with(['content' => $this->content]); // withでセットしたデータをviewへ渡す } }5. Controllerの設定
Controller側では送信先とMailableクラスの振り分けを行う
Controlleruse App\Mail\OrderMail; use Illuminate\Support\Facades\Mail; public function store(Request $request){ // フォームからのリクエストデータ全てを$contentに代入 $content = $request->all(); // 特に変数を渡さない場合 Mail::to($content->email)->send(new SapmleMail); // データの入った変数を渡す場合 Mail::to($content->email)->send(new SampleMail($content));6. メール本文のテンプレート
Mailableクラスで設定したviewのメール本文のテンプレートの作成
views/mail/send.blade.php// withで変数を受け取った場合は変数を使用できる {{ $contact->name }} 様 メール送信完了7. メールの送信
以上で、メール送信機能が完成。
mailtrapではこのような感じでで表示されるようになる。
- 投稿日:2019-08-29T17:46:32+09:00
Laravelでリレーションされているデータをpaginateする
色々躓いたのでまとめておきます。
前提
PHP 7.0
Laravel 5.5データ構造
Work
id category_id title 1 1 なんかのしごと WorkCategory
id name 1 未分類 やりたいこと
上記データ構造のデータを下記のような形で返すAPIを作りたい
{ "id": "1", "category_name": "未分類", "title": "なんかのしごと" }かつ、Laravelさんのページネーション情報つきで!
1対1リレーションするようにモデルを変更する
Work.phpclass Work extends Model { public function workCategory() { return $this->hasOne('App\models\WorkCategory', 'id', 'category_id'); } }躓いたこと
workCategory
ではなくcategoryName
にして名前だけ直接取ろうとして、なんか色々だめでした。
素直に関連するモデル名にしたらすんなり動きました。下記だめだったコード
だめだったコードclass Work extends Model { public function categoryName() { return $this->hasOne('App\models\WorkCategory', 'id', 'category_id')->name; } }主に
name
が存在しないという感じで怒られていました。
また、名前だけを取る方法をやめWorkCategory
自体を持つように変えています。EagerLoad を使う
Work::paginate(9);
ではなくWork::with('workCategory')->paginate(9);
を使う。WorkRepository.phpclass WorkRepository { public function getPaginateWorks() { return Work::with('workCategory')->paginate(9); } }Resources を用意してJSONに変換する
Laravel 5.5 Eloquent: APIリソース のようにモデルをJSONに変換する層が用意されているみたいです。
$ php artisan make:resource PaginatedWorks --collection
artisan
にリソースを作ってもらって、先程の変換ロジックを入れます。PaginatedWorks.phpclass PaginatedWorks extends ResourceCollection { public function toArray($request) { return ['data' => $this->collection->transform([$this, 'map'])]; } public function map($work) { return [ 'id' => $work->id, 'category_name' => $work->workCategory->name, 'title' => $work->title ]; } }paginate 内のデータ変換には
transform
メソッドを使うと良いみたいです。callable は配列で渡してもOK
Resouces
を知る前に書いていたのでRepository
になっていますWorkRepository.phpclass WorkRepository { public function getPaginateWorks() { $works = Work::with('workCategory')->paginate(9); $works->getCollection()->transform([$this, 'map']); return $works; } public function map(Work $work) { return [ 'id' => $work->id, 'category_name' => $work->workCategory->name, 'title' => $work->title ]; } }はじめのうち
transform
に$this->map
を渡していて
Undefined property: App\\Repositories\\WorkRepository::$map
と怒られていました。
調べたところ[$this, 'map']
という風に配列で渡してやれば実行してくれるとのこと。
渡す配列は1つ目にインスタンス、2つ目に実行するメソッド名の文字列。下記だめだったコード
だめだったコードclass WorkRepository { public function getPaginateWorks() { $works = Work::with('workCategory')->paginate(9); $works->getCollection()->transform($this->map); return $works; } private function map(Work $work) { return [ 'id' => $work->id, 'category_name' => $work->workCategory->name, 'title' => $work->title ]; } }渡したいメソッドを
private
で定義していたところも躓いていました。
なお PHP7.1 以上であれば private で渡せる方法がある模様です。結果
WorkController.phpclass WorksController extends Controller { public function __construct() { } public function index(Request $request) { $paginatedWorks = (new WorkRepository())->getPaginatedWorks(); return new PaginatedWorks($paginatedWorks); } }Work.phpclass Work extends Model { public function workCategory() { return $this->hasOne('App\models\WorkCategory', 'id', 'category_id'); } }WorkRepository.phpclass WorkRepository { public function getPaginateWorks() { return Work::with('workCategory')->paginate(9); } }PaginatedWorks.phpclass PaginatedWorks extends ResourceCollection { public function toArray($request) { return ['data' => $this->collection->transform([$this, 'map'])]; } public function map($work) { return [ 'id' => $work->id, 'category_name' => $work->workCategory->name, 'title' => $work->title ]; } }Response{ "data": [ { "id": 1, "category_name": "\u672a\u5206\u985e", "title": "\u30af\u30ec\u30b9\u30c8\u30db\u30fc\u30eb\u30c7\u30a3\u30f3\u30b0\u30b9 \u30b3\u30fc\u30dd\u30ec\u30fc\u30c8\u30b5\u30a4\u30c8\u5236\u4f5c" } ], "links": { "first": "\/api\/works?page=1", "last": "\/api\/works?page=1", "prev": null, "next": null }, "meta": { "current_page": 1, "from": 1, "last_page": 1, "path": "\/backoffice\/api\/works", "per_page": 9, "to": 1, "total": 1 } }
Response
のpath
は少し変えてます。
- 投稿日:2019-08-29T04:11:57+09:00
CodenvyでLaravelデビューする
何するの
CodenvyでLaravelの実行環境を作るよ。
個人用メモ
## なんか画像が入らないので後で差し込む事前準備
Codenvyのアカウント登録しておく
ワークスペースを作る
Create WorkSpace
からワークスペースを作成する。
NAME
は任意のワークスペース名を指定。
TEAM
は個人ならpersonalで。
SELECT STACK
はPHPを選択。
あとは基本的にいじらなくてよし。Laravelプロジェクトを作る
Create Project...
からプロジェクトを作成する。
PHPのComposerを指定。
Name
は任意のプロジェクト名を指定。
Description
も任意で記入。
Next
で次に進む。
Package Name
にlaravel/laravel
を指定。
Create
Laravelプロジェクトを実行するための準備
ファイル名を直す
.env.sample
ファイルを.env
に修正する。cd [各プロジェクト名] cp -p .env.example .env php artisan key:generate実行用のコマンドを作る
Create new command
からコマンド作成ダイアログを表示する。
Name
は任意のコマンド名を指定。
Command line
には以下を指定。cd ${current.project.path} && php artisan serve --host=0.0.0.0 --port=3306
Apply to
は当プロジェクトのApplicable
をYes
に設定する。
Preview URL
は以下を指定。http://${server.port.3306}
Save
実行してみよう
上で登録した実行用のコマンドを実行してみる。
実行はCreate new command
したところから。OK!
- 投稿日:2019-08-29T01:38:05+09:00
Laravel 5.7でControllerのファイル名を少し変更(大文字)しただけなのに、Controllerファイルが見つからないエラーが出るようになった
問題
すでに作ったControllerファイル名を変更(大文字・小文字)したら、ファイルが見つからないエラーが出てサイトが動かなくなった。表示されたエラーは以下の通り:
ErrorException (E_WARNING) include(/hogehoge/backend/vendor/composer/../../app/Http/Controllers/NameOfController.php): failed to open stream: No such file or directory環境と経緯
- Laravel 5.7使用。
- "php artisan make:controller nameOfController"でコントローラを追加。
- 自動生成されたファイルの名前(nameOfController.php)を、のちに"NameOfController.php"へ変更。
- ファイル名を変更した後で、routes/web.phpには、"Route::get('/entrance', 'NameOfController@hoge')->name('hoge');"を追加。
- 前述の問題が発生。ErrorException・No such file or directoryエラーが発生し、サイトが動かなくなった。
解決策
ターミナルで、"composer dump-autoload"をlaravelプロジェクトのルートディレクトリで実行する。こちらのブログが参考になりました。
背景
コントローラを作っていくうちに、コントローラファイル名のケーススタイルがバラバラになってきた(camelCase名で作ったコントローラよりPascalCaseの方が多くなってきた)ため、手に負えなくなる前に統一しておこうと思った途端に起きた問題でした。
- 投稿日:2019-08-29T00:09:23+09:00
Homeateadで立ち上げたLaravel環境にsequel ProでDB接続
なんだかんだ毎月記事を投稿していて8月は何もアウトプット出来ていなかったので急ぎ足で記事を書く。。。
最近Laravelを使った開発をしていて自宅のMacにもLaravel環境を構築してDB接続にsequel proを使ったので記事に残します。環境構築を終えホスト設定を済ませブラウザからLaravelのトップページが表示が出来ているという前提です。
データベースに接続するためにSequel proを使用します。
作成したプロジェクトディレクトリ内にある.envファイルを開くとDBの情報が記載されています。
記載されいる情報を確認しながらsequel proに必要な情報を入力すれば立ち上げている仮想環境内のDBに接続できます。
- 名前
- localhostやtest-laravelなど、任意に指定できます。
- ホスト
- これはhomestead.ymlに記述してあるIPを参照すればOKです。
homestead.ymlip: "192.168.xxx.xxx"
- ユーザ名/パスワード/ポート
- 自身の.envファイルを参照すればOKです。
DB_USERNAME=homestead DB_PASSWORD=xxxxxx DB_PORT=3306これだけでDBへ接続できると思います。
コマンドラインからもDB情報は見れますがクライアントツールを上手く使えば見やすくなります。