- 投稿日:2020-11-15T19:56:45+09:00
Laravel Mixを使用してSCSSをCSSにコンパイルしてみよう
開発環境
- Laravel 8.0
- php 7.3
- laravel-mix 5.0.1
はじめに
今回はlaravelにSCSSを導入してから実際にコンパイルするまでの流れを記事にしています。
※すでにLaravelプロジェクトを立ち上げている前提での手順になりますのでご了承くださいLaravel Mix
Laravel Mixとは、フロントエンドのアセットをコンパイル、バンドルしてくれるツール。
ツールの中身はwebpackを利用しているwebpackを使うと何がいいの?
・依存性を解決できる
・リクエスト数を減らすことができるSCSSを導入するにあたって本記事ではLaravel Mixを使用します。
すでに、package.jsonにLaravel Mixは最初から記述されているためターミナルでnpm installしちゃいましょう$ npm install
次にwebpack.mix.jsを開いてみるとこんな感じになってます
webpack.mix.jsとはwebpackというJavaScriptパッケージツールで使うもの(ラッパー)
const mix = require('laravel-mix'); /* |-------------------------------------------------------------------------- | Mix Asset Management |-------------------------------------------------------------------------- | | Mix provides a clean, fluent API for defining some Webpack build steps | for your Laravel applications. By default, we are compiling the CSS | file for the application as well as bundling up all the JS files. | */ mix.js('resources/js/app.js', 'public/js') .postCss('resources/css/app.css', 'public/css', [ // ]);
実際にコンパイルしてみる
まずはresources内にsassディレクトリを作成して、その中にapp.scssを作成します。
そして、webpack.mix.jsを下記内容に編集
const mix = require('laravel-mix'); /* |-------------------------------------------------------------------------- | Mix Asset Management |-------------------------------------------------------------------------- | | Mix provides a clean, fluent API for defining some Webpack build steps | for your Laravel applications. By default, we are compiling the CSS | file for the application as well as bundling up all the JS files. | */ mix.js('resources/js/app.js', 'public/js') .sass('resources/sass/app.scss', 'public/css'); // resources/sass/app.scssを参照して、public内にcssのファイルを作成します
編集したらターミナルでnpm run dev
$ npm run dev
成功したら、public内にcssが生成されているのを確認してください。
以上でLaravel Mixを使用してSCSSを導入するまでの流れになります。
補足
バンドル(合体)してコンパイルするケース↓↓
// jsファイルをバンドル(合体)したい場合 mix .scripts([ 'public/js/app.js' , 'public/js/app2.js' ], 'public/js/all.js' ); //[admin.jsとdashboard.js]を all.js としてバンドル(合体)させます。 // cssファイルをバンドル(合体)したい場合 mix .styles([ 'public/css/app.css' , 'public/css/app2.css' ], 'public/css/all.css' ); // app.css と app2.css をバンドル(合体)させて // publicフォルダに all.css を作成します。
5:各views/○○○○.blade.phpでの使用方法
<!-- Scripts(JSの場合※srcで呼び出します。) --> <script src="./public/index.js"></script> <!-- Styles(CSSの場合※hrefで呼び出します。) --> <link href="{{ asset('css/app.css') }}" rel="stylesheet">
便利コマンド
公式ドキュメント参照
npm run watch
コマンドはターミナルで実行し続け、関連ファイル全部の変更を監視します。
Webpackは変更を感知すると、アセットを自動的に再コンパイルします。npm run watch-poll
特定の環境のWebpackでは、ファイル変更時に更新されないことがあります。
自分のシステムでこれが起きた場合は、watch-pollコマンドを使用してください。
- 投稿日:2020-11-15T19:56:45+09:00
Laravel Mixを使用してSCSSを導入してみよう
開発環境
- Laravel 8.0
- php 7.3
- laravel-mix 5.0.1
はじめに
今回はlaravelにSCSSを導入してから実際にコンパイルするまでの流れを記事にしています。
※すでにLaravelプロジェクトを立ち上げている前提での手順になりますのでご了承くださいLaravel Mix
Laravel Mixとは、フロントエンドのアセットをコンパイル、バンドルしてくれるツール。
ツールの中身はwebpackを利用しているwebpackを使うと何がいいの?
・依存性を解決できる
・リクエスト数を減らすことができるSCSSを導入するにあたって本記事ではLaravel Mixを使用します。
すでに、package.jsonにLaravel Mixは最初から記述されているためターミナルでnpm installしちゃいましょう$ npm install
次にwebpack.mix.jsを開いてみるとこんな感じになってます
webpack.mix.jsとはwebpackというJavaScriptパッケージツールで使うもの(ラッパー)
const mix = require('laravel-mix'); /* |-------------------------------------------------------------------------- | Mix Asset Management |-------------------------------------------------------------------------- | | Mix provides a clean, fluent API for defining some Webpack build steps | for your Laravel applications. By default, we are compiling the CSS | file for the application as well as bundling up all the JS files. | */ mix.js('resources/js/app.js', 'public/js') .postCss('resources/css/app.css', 'public/css', [ // ]);
実際にコンパイルしてみる
まずはresources内にsassディレクトリを作成して、その中にapp.scssを作成します。
そして、webpack.mix.jsを下記内容に編集
const mix = require('laravel-mix'); /* |-------------------------------------------------------------------------- | Mix Asset Management |-------------------------------------------------------------------------- | | Mix provides a clean, fluent API for defining some Webpack build steps | for your Laravel applications. By default, we are compiling the CSS | file for the application as well as bundling up all the JS files. | */ mix.js('resources/js/app.js', 'public/js') .sass('resources/sass/app.scss', 'public/css'); // resources/sass/app.scssを参照して、public内にcssのファイルを作成します
編集したらターミナルでnpm run dev
$ npm run dev
成功したら、public内にcssが生成されているのを確認してください。
以上でLaravel Mixを使用してSCSSを導入するまでの流れになります。
補足
バンドル(合体)してコンパイルするケース↓↓
// jsファイルをバンドル(合体)したい場合 mix .scripts([ 'public/js/app.js' , 'public/js/app2.js' ], 'public/js/all.js' ); //[admin.jsとdashboard.js]を all.js としてバンドル(合体)させます。 // cssファイルをバンドル(合体)したい場合 mix .css([ 'public/css/app.css' , 'public/css/app2.css' ], 'public/css/all.css' ); // app.css と app2.css をバンドル(合体)させて // publicフォルダに all.css を作成します。
5:各views/○○○○.blade.phpでの使用方法
<!-- Scripts(JSの場合※srcで呼び出します。) --> <script src="./public/index.js"></script> <!-- Styles(CSSの場合※hrefで呼び出します。) --> <link href="{{ asset('css/app.css') }}" rel="stylesheet">
便利コマンド
公式ドキュメント参照
npm run watch
コマンドはターミナルで実行し続け、関連ファイル全部の変更を監視します。
Webpackは変更を感知すると、アセットを自動的に再コンパイルします。npm run watch-poll
特定の環境のWebpackでは、ファイル変更時に更新されないことがあります。
自分のシステムでこれが起きた場合は、watch-pollコマンドを使用してください。
- 投稿日:2020-11-15T19:35:14+09:00
homesteadでngrok使う(style崩れる)
homesteadでngrokを使用しハマったこと
・mac
・Laravel 6
・homestead 9.6.1
・ngrok 2.3.35vagrant sshでログイン
作業ディレクトリに移動ターミナルvagrant@homestead:~/code/app$ share homestead.testこれで作成されたURLでアクセスできる。
開発で使用しているPCではしっかりと表示されているが、URLをスマホに送り
スマホで見ると、CSS、画像などが反映されていない。原因
どうやら、asset関数が読み込まれていない。
hoge.blade.php<link rel="stylesheet" href="{{ asset('/css/style.css') }}" />これならしっかり反映される
hoge.blade.php<link rel="stylesheet" href="css/style.css" />しかし、トップページから違うページに飛ぶと、ページが表示されない
例(home => about)など解決法
vagrantではなくmacにngrokをインストールする
vagrant作業ディレクトリで
ターミナルvagrant@homestead:~/code/app$ php artisan serve Laravel development server started: http://127.0.0.1:8000ターミナル 別タブ
ターミナルhogehoge@hogehogeAir app % ngrok http 8000
生成されたURLに接続すればOK
これが正解か分かりませんが、これで上手く接続出来ます。
もっといい方法あれば教えてください。
- 投稿日:2020-11-15T17:38:43+09:00
【Laravel】エラー Fatal Error Unable to create lock file: Bad file descriptor (9)
php artisan serve で、サーバーが起動できなくなった。
原因
- 全ユーザーが書き込み可能なハズのtmpディレクトリに、書き込み権限がなくなってた。。パーミッションエラー!
解決方法
権限を与えて解決% ls -ld /private/tmp // 確認 drwxr-xr-x 22 root wheel 704 11 15 16:59 /private/tmp // ↑ tがない % sudo chmod 1777 /private/tmp // 権限を付与 % ls -ld /private/tmp // 確認 drwxrwxrwt 22 root wheel 704 11 15 16:59 /private/tmp // ↑ tがついた % php artisan serve // 起動できた
- パーミッションのマーク : 「 t 」って?
- スティッキービット(Sticky Bit、全ユーザーが書き込みを行える権限)のこと。
- 削除は、所有者とrootだけ可能。
スティッキービットを設定方法% chmod 1777 ディレクトリ名 // パーミッション値 +1000
- 投稿日:2020-11-15T15:03:44+09:00
バリデーションのメッセージ カスタマイズしてみた
バリデーションのメッセージカスタマイズ
validation.phpの中エラーメッセージを変更せずに、オリジナルのバリデーションメッセージを
設定してバリデートメッセージを出せたので記事にしました。基本的には英語ですが、validation.phpの中に設定されています。
日本語版は下記から確認できます。
https://readouble.com/laravel/5.6/ja/validation-php.html一部ですが、こんな感じでバリデーションメッセージが設定されています。
attributeは好きなように設定できます。'required'=> ':attributeは必須です。', 'unique' => ':attributeは既に存在します。', 'attributes' => [ 'first_name'=>'姓名', 'last_name'=>'姓名', ]下記のようにバリデーションを設定できます。
このように設定すると、first_name、last_nameが空欄の場合、
姓名は必須です。などとエラーメッセージが出力されます。
public function rules() { return [ 'first_name' => 'required', 'last_name' => 'required', ]; }
例えば、他のbladeではattributeは必要です。としたい場合、
'required'=> ':attributeは必要です。',
上記のように変えてあげればよいのですが、そうすると先程のエラーメッセージも変わってしまいます。
ここのページだけメッセージを変えるということができるのです。結論、messages()メソッドを設定できます。
下記のように設定してあげると、実現できます。public function messages() { return [ 'first_name.required' => ':attributeは必要です。' 'last_name.required' => ':attributeは必要です。' ]; }まとめ
messages()メソッドを追加して、first_name.requiredとドット区切りで指定すると、メッセージのみ変更可能でした。
- 投稿日:2020-11-15T14:11:41+09:00
【Laravel】リダイレクトの書き方メモ
- リダイレクト定義の書き方について。
リダイレクトの基本// httpの場合 return redirect('test/index'); // http://xxxxx/test/index return redirect()->to('test/index'); // ↑と同義 return redirect('test/index', 301); // ステータスコードを指定する場合(※ デフォルトは、302) return redirect('test/index', 301, ['test-header' => 'テスト'] ); // HTTPヘッダー を追加する場合 // httpsの場合 return redirect('test/index', 302, [], true); // https://xxxxx/test/index // ルート名での指定 return redirect()->route('test.list'); return redirect()->route('test.show', ['id' => 12]); // id情報を含むルーティングの場合(例: test/{id} ) $user = App\User::find(12); // ↑と同義 return redirect()->route('test.show', ['id' => $test]); // コントローラ名での指定 return redirect()->action('TestController@index'); return redirect()->action('TestController@show', ['id' => 12]); // id情報を含む場合パス、アクションの指定
パス、アクションの指定return redirect($to = null, $status = 302, $headers = [], $secure = null); // パスの指定 return redirect()->to($path, $status = 302, $headers = [], $secure = null); // 取得インスタンスへのパス指定 return redirect()->route($route, $parameters = [], $status = 302, $headers = []); // 取得インスタンスへのルート指定 return redirect()->action($action, $parameters = [], $status = 302, $headers = []); // 取得したインスタンスへアクション指定 return redirect()->away($path, $status = 302, $headers = []); // 取得したインスタンスへの外部ドメインの指定 // コントローラを使わず、リダイレクト先を指定する場合 Route::redirect($uri, $destination, $status = 301);データも一緒にリダイレクト
セッションデータと一緒にリダイレクト(※フラッシュメッセージなどに使う)return redirect('home')->with('result', '完了'); return redirect('home')->with([ // 複数データを格納する場合は、配列で! 'result_1'=>'成功-1', 'result_2'=>'成功-2', 'result_3'=>'成功-3' ]); // ビューで取得 {{ session('result') }}直前ページへのリダイレクト
直前ページにリダイレクト// 基本 public function back() { return back(); } // データも一緒に、直前ページに戻す場合 public function back() { return back()->with('result', 'ok!'); return back()->withInput(); // 送信データがセッション内に格納される } // ビューで取得 {{ session('result') }} // 例 public function back(Request $request) { return back()->withInput($request->only(['email'])); } // ビューで取得 <textarea name="message">{{ old('message') }}</textarea>
- 投稿日:2020-11-15T14:11:28+09:00
コマンドなしでGithubにコードをアップロードして、Github Desktopに追加する方法
こんにちは、くりぱんです。
この記事で実現できること
- Githubにコードをアップロードできる
- Github Desktopにアップロードしたリポジトリを追加できる
開発環境
- OS:MacOS
- Git:2.29.2
説明
私は個人開発や個人学習のために、Githubへコードをアップロードしています。
また、コードを簡単に管理できるように、Github Desktopを使用しています。
今回は、Githubへコードをアップロードしてもらい、Github Desktopを使用してコードを管理できるようにする方法を説明していきます。簡単実装
実装準備
Githubのアカウントを下記から取得してください。
https://github.com/Github Desktopを下記からダウンロードしてください。
https://desktop.github.com/Github
①にfirst_githubと入力して、②のCreate repositoryをクリック
※ ①のfirst_githubは任意の名前で大丈夫です。
Finderで今回アップロードするコードが入ったフォルダを選択し、開くをクリック
私の場合は、今回/Applications/MAMP/htdocs/first_github
というLaravelのプロジェクトをGithubにアップロードするので、'first_github'を選択しています。
これで自由にコード管理ができるようになります!
Github Desktopは、とても簡単に操作できるのでぜひ使ってみてください!最後に
コマンドなしでGithubにコードをアップロードして、Github Desktopでコマンドなしでコミットやマージなど何でもできます。初学者の方にも扱いやすいので、ぜひ良いコード管理ライフをお楽しみください!
Twitterもやってます!
プログラミングや金融知識、英語、エンジニアの現実についてつぶやいています!
よかったら見てみてくださいね!
- 投稿日:2020-11-15T13:15:47+09:00
Homestead をアップデートしたい
アップデートの方法がどこにもないので、 box の最新版を追加し、 git のソースも最新化した (方法はこちら)。
ただし、この方法だとデータベースの中身が引き継がれない。
もし最新化する前であれば、普通にvagrant ssh
でmysqldump
するだけ。
ダンプの仕方を知りたい人は飛ばしてこちら。自分みたいにうっかり更新した後で、旧 Homestead のデータを取り出したいとなった人は次へ。
データベース内容の引き継ぎ
- VirtualBox から旧 Homestead を直接起動
- GUI でログインする(login:
vagrant
, Password:vagrant
)- mysqldump する
- ホストのコンソールから scp で取り出す
- 旧 Homestead シャットダウンする
- 新 Homestead を
vagrant up
で起動する- 先程のダンプファイルをゲストと共有しているフォルダに入れる
vagrant ssh
でゲストに入り、共有フォルダに移動する- マイグレーションを実行する
- ダンプを mysql に流し込む
ダンプの仕方
データだけとる
大抵の人はマイグレーションを利用しているので、ダンプはデータだけ取れれば良いはず。
database
とbk_databas.sql
はそれぞれ自分に合ったものに変更する。mysqldump -t `database_name` --ignore-table=migrations > bk_databas.sqlスキーマも一緒に
マイグレーションを利用していない場合は以下になる。
-t
があるかどうかの違い。mysqldump `database_name` > bk_databas.sql最新化
- Homestead.yaml のバックアップ (例:
cp Homestead.yaml Homestead.yaml.bk
)vagrant box update
git fetch
git checkout release
bash init.sh
- いくつか聞かれるが全部
y
- Homestead.yaml の差分を確認し、プロジェクトに必要なところを戻す
- デフォルトのPHPバージョンが変更になっている場合は、以前のやつに設定する (例:
php72
)ライブラリとかは何もしなくてもそのまま引き継がれているはずなので、 composer とかは基本的にやらなくて良いはず。
自分のプロジェクトの PHP バージョンが分かっているのであれば、Homestead.yaml
のsites
ディレクティブで該当のプロジェクトにphp: "7.2"
と記載するのが良いと思う。
- 投稿日:2020-11-15T12:10:18+09:00
Laravel6系エラー、/login の表示がView [auth.login] not found.の対策
Laravel6 で認証画面を作ろうとしたらエラーがでました。
その対策についての内容になります。現象
/login
へのアクセスでエラーが出ました。エラー表示InvalidArgumentException View [auth.login] not found.
auth.login
というビューがないとエラーになっています。環境
環境は Laravel6.x です。
Laravelのバージョンphp artisan --version Laravel Framework 6.20.3対策
Laravel6 から laravel/ui が必要らしいです。
composer から入れます。composer require laravel/ui 1.*自分は Mac と Docker の環境でメモリの都合で以下のコマンドから入れました。
php -d memory_limit=-1 /usr/local/bin/composer require laravel/ui 1.*確認
/login
へアクセスしいます。参考
- 投稿日:2020-11-15T11:48:57+09:00
Laravel6 改行をビューで表示する
目的
- PHPのエスケープシーケンスを用いた改行をビューで表示する方法をまとめる
実施環境
- ハードウェア環境
項目 情報 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.8 Homebrewを用いてこちらの方法で導入→Mac HomebrewでPHPをインストールする Laravel バージョン 6.X commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う MySQLバージョン 8.0.19 for osx10.13 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする 前提条件
- 実施環境に近い開発環境が用意できていること。
- ローカルサーバを起動する事ができるLaravel6のアプリケーションが存在していること。
前提情報
- PHPのエスケープシーケンスを用いて改行を含んだ文字列をビューで改行して表示したい。
ブラウザでは下記のように表示してほしい。
A <br> B <br> C概要
- ルーティング情報の記載
- コントローラファイルの作成と記載
- ビューファイルの作成と記載
- 確認
詳細
ルーティング情報の記載
Laravelアプリ名ディレクトリで下記コマンドを実行してルーティングファイルを開く。
$ vi routes/web.php下記のルーティング情報を追記する。
Laravelアプリ名ディレクトリ/routes/web.phpRoute::get('/index', 'TestController@index')->name('index');コントローラファイルの作成と記載
Laravelアプリ名ディレクトリで下記コマンドを実行してコントローラファイルを作成する。
$ php artisan make:controller TestControllerLaravelアプリ名ディレクトリで下記コマンドを実行してコントローラファイルを開く。
$ vi app/Http/Controllers/TestController.php下記のアクションをコントローラファイルに記載する。
Laravelアプリ名ディレクトリ/app/Http/Controllers/TestController.phppublic function index() { /* シングルクオートで文字列を囲むとエスケープシーケンスが文字列扱いされるので注意 */ $str = "A\nB\nC"; return view('tests.index', ['str' => $str]); }記載後のコントローラファイルの全体の内容を下記に記載する。
Laravelアプリ名ディレクトリ/app/Http/Controllers/TestController.php<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class TestController extends Controller { // 下記を追記する public function index() { /* シングルクオートで文字列を囲むとエスケープシーケンスが文字列扱いされるので注意 */ $str = "A\nB\nC"; return view('tests.index', ['str' => $str]); } // 上記までを追記する }ビューファイルの作成と記載
Laravelアプリ名ディレクトリで下記コマンドを実行してビューファイルを格納するディレクトリを作成する。
$ mkdir -p resources/views/testsLaravelアプリ名ディレクトリで下記コマンドを実行してビューファイルを作成して開く。
$ vi resources/views/tests/index.blade.php下記の内容を記載する。
Laravelアプリ名ディレクトリ/resources/views/tests/index.blade.php<p>{!! nl2br(e($str)) !!}</p>確認
Laravelアプリ名ディレクトリで下記コマンドを実行してローカルサーバを起動する。
$ php artisan serve下記にアクセスする。
下記のようにABCがそれぞれ改行されて表示されることを確認する。
検証
変数に入った文字列をビューファイルで表示する際、本来は
{{ }}
でくくって表示するが今回は{!! !!}
でくくっている。試しにビューファイルの記載を{{ }}
にして$strだけを表示してみる。{!! nl2br(e($str)) !!}の簡単な解説
e($str)
の説明
- 変数$strに格納された文字列の中の「& (アンパサンド)」「" (ダブルクォート)」「' (シングルクォート)」「< (小なり)」「> (だいなり)」を別の文字に変換している。
- もし仮に$strにXSS攻撃を意図としたリンクなどが含まれていたときに悪意のあるリンクタグを表示されないようにエスケープする。
nl2br()
の説明
- PHPのエスケープシーケンス(
\n
など)からhtmlのタグ(<br>
など)を作成する関数である。- これは変数$strに格納されている
\n
をhtmlの<br>
に置き換えてくれている。(正確には\n
の直前に<br>
を追記してくれている。){!! !!}
の説明
- 通常の
{{ }}
はXSS攻撃を予防するために特殊文字を勝手にエスケープしてしまう。
- https://readouble.com/laravel/6.x/ja/blade.html「Tip!! Bladeの{{ }}記法はXSS攻撃を防ぐため、自動的にPHPのhtmlspecialchars関数を通されます。」
- これは関数
nl2br()
て作成した<br>
タグの例外ではなくエスケープされてしまう。
- https://readouble.com/laravel/6.x/ja/blade.html「エスケープしないデータの表示 デフォルトでブレードの{{ }}文はXSS攻撃を防ぐために、PHPのhtmlspecialchars関数を自動的に通されます。しかしデータをエスケープしたくない場合は、以下の構文を使ってください。」
- まとめると「
{!! !!}
を使用しないとnl2br()
で作成した<br>
がエスケープされてしまう。しかし{!! !!}
はXSS攻撃される可能性がある。それを防ぐためにnl2br()
にわたす変数$strには特殊文字が入っていたら困る。nl2br()
にわたす前にXSS攻撃と思しき特殊文字はエスケープして渡す」という感じ。おまけ
PHPのhtmlspecialchars関数について
{{ }}
を用いたビューファイルの表示はPHPのhtmlspecialchars関数を通したものであるらしい。
- https://readouble.com/laravel/6.x/ja/blade.html「Tip!! Bladeの{{ }}記法はXSS攻撃を防ぐため、自動的にPHPのhtmlspecialchars関数を通されます。」
- PHPのhtmlspecialchars関数が何をしているのかを気になったので調べてみる。下記にPHPドキュメントのリンクを記載する。
当該関数を通すと下記の特殊文字列が変換される。
なので
{{ }}
を通して表示する文字列は上記の変換が行われた上で表示が行われる。htmlspecialchars関数を迂回して表示したいときは
{!! !!}
を使用する。Laravelで意図的にhtmlspecialchars関数で特殊文字列を変換したいときはヘルパ関数
e()
を使用する。脆弱性の観点からみて今回のような特殊ケースを覗いて
{!! !!}
は多用しないほうが良いと思う。特殊ケースで
{!! !!}
を使用するとしてもLaravelならヘルパ関数e()
を併用するなど攻撃に対する対策が必要であると考える。
- 投稿日:2020-11-15T00:30:38+09:00
[Laravel] 画像アップロード機能
簡単なCRUD機能を作成した際に画像アップロード機能を作成しましたのでまとめました。
ビューファイルに反映
create.blade.php@section('content') <div class="container" style="margin-top:150px;"> <div class="row"> <div class="col-12"> <div class="card mt-3"> <div class="card-body pt-0"> @include('error_card_list') <div class="card-text"> <form method="POST" enctype="multipart/form-data" action="{{ route('tweets.store') }}"> @include('tweets.form') <button type="submit" class="btn blue-gradient btn-block">投稿する</button> </form> </div> </div> </div> </div> </div> </div> @endsectionform.blade.php@csrf <div class="md-form"> <label>タイトル</label> <input type="text" name="title" class="form-control" required value="{{ $tweet->title ?? old('title') }}"> </div> <div class="form-group"> <label></label> <textarea name="content" required class="form-control" rows="16" placeholder="本文">{{ $tweet->content ?? old('content') }}</textarea> </div> <div class="form-group"> <input type="file" name="tweet_img" type="file" value="{{ old('tweet_img')}}" > </div> <div class="md-form"> <label>住所</label> <input type="text" name="address" class="form-control" required value="{{ $tweet->address ?? old('address') }}"> </div>① "enctype" => "multipart/form-data"
二つ以上のファイルを同時にリクエストに格納するための方式。画像アップロードのフォームには必須。② csrf
クロスサイトスクリプティングというWebアプリケーションの脆弱性の略称で、上記のinputタグはこの脆弱性からWebサービスを守るためのトークン情報です。POST送信を行う際は、必須となります。③ old関数
入力した内容が保持された状態で登録画面が表示されるようになり、ユーザーはエラーになった箇所だけを修正すれば良くなります。以下が画像アップロードに関する記載になります。
nameは各自好きな名前に設定して下さい。
create.blade.php<form method="POST" enctype="multipart/form-data" action="{{ route('tweets.store') }}"> @include('tweets.form') <button type="submit" class="btn blue-gradient btn-block">投稿する</button> </form>form.blade.php<div class="form-group"> <input type="file" name="tweet_img" type="file" value="{{ old('tweet_img')}}" > </div>モデル作成
Tweet.php<?php namespace App; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; class Tweet extends Model { //不正なリクエストによってtweetsテーブルが予期せぬ内容に更新されることを防ぐ protected $fillable = [ 'title', 'content', 'address', 'tweet_img' => 'image|file' ]; //もしuserメソッドがBelongsToクラスではなく、整数や文字列などの別の型を返そうとした場合、その時点でTypeErrorという例外が発生して処理が終了 public function user(): BelongsTo { //$thisはTweetクラスのインスタンス自身を示す return $this->belongsTo('App\User'); } }画像アップ用コントローラー設定
TweetController.phppublic function store(TweetRequest $request, Tweet $tweet) { if ($file = $request->tweet_img) { $fileName = time() . $file->getClientOriginalName(); $target_path = public_path('uploads/'); $file->move($target_path, $fileName); } else { $fileName = ""; } $tweet->fill($request->all()); $tweet->user_id = $request->user()->id; $tweet->tweet_img = $fileName; $tweet->save(); return redirect('/'); }コントローラーがややこしいので詳細を説明いたします。
if ($file = $request->profile_img) { $fileName = time() . $file->getClientOriginalName(); $target_path = public_path('uploads/'); $file->move($target_path, $fileName); } else { $fileName = ""; }この部分では、
$file
にformからくる画像の情報が入っています。
画像が場合は、$fileName
を空文字にしています。・
getClientOriginalName()
拡張子を含め、アップロードしたファイルのファイル名を取得することができます。
・time()
タイムスタンプを取得します。
・public_path()
publicディレクトリの完全パスを返します。ここでは、publicディレクトリ内にuploadsディレクトリを作成しています。
・$file->move($target_path, $fileName)
画像をpublic/uploads/に、$fileNameという名前で挿入しています。$tweet->fill($request->all()); $tweet->user_id = $request->user()->id; $tweet->tweet_img = $fileName; $tweet->save(); return redirect('/');・
$tweet->fill($request->all());
リクエストのallメソッドを使用することでPOSTリクエストのパラメータをtokenを配列型式で表示できます。[ "_token" => "CdU7HghsXIOi14n7UnwCeOALRPGiVkMegZmK6RDc", "title" => "画像とは", "content" => "画像はアップロードできます。", ]そして、Tweetモデルのfillメソッドにこの配列を渡すと、Tweetモデルのfillableプロパティ内に指定しておいたプロパティ(ここではtitleとcontent、address、tweet_img)のみが、$tweetの各プロパティに代入されます。
fillableプロパティを定義したことで、クライアントからのリクエストのパラメーター値をそのまま取り込んで更新しても良いプロパティは、titleとcontent、address、tweet_imgのみと制限されるようになりました。
不正なリクエストによってtweetsテーブルが予期せぬ内容に更新されることを防ぐようになりました。
注目するべきは、
$tweet->tweet_img = $fileName;
です。
データベースには、画像の名前しか保存していません。画像を表示
画面に画像を表示できるようにするためにlaravelの公開用publicフォルダにシンボリックリンクを貼ります。
php artisan storage:link;最後にブラウザへ出力しましょう。
index.phpdiv class="container" style="margin-top:50px;"> @foreach($tweets as $tweet) <div class="card-body"> <img src="/uploads/{{$tweet->tweet_img}}"class="img-fluid" alt="Responsive image"> </div> @endforeach </div>今までの作業は、データベースには画像の名前だけを保存して、画像本体はpublicディレクトリ内のuploadsの中に保存したことになります。
srcの部分は人によって変わります。