20210425のlaravelに関する記事は11件です。

Laravel バリデーションを実装したら403エラーが帰ってきた

目的 Laravelで新規のRequestクラスを作成してバリデーションを実装したら403エラーが返されたので何が間違えていたかメモ的にまとめる 原因 Requestクラスの中のauthorize()メソッドの戻り値がfalseのままだった。 Request.php /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return false; } 「Determine if the user is authorized to make this request.」と記載されており、翻訳すると「ユーザーがこの要求を行うことを許可されているかどうかを判別します。」と説明されている。 ユーザーからPostされたデータをバリデートしたい時は当該メソッドの戻り値をtrueに設定する必要がある。 Request.php /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; } 教えていただいた内容 @nunulk様にコメントで教えていただきました。 ユーザーによる要求の許可の必要がない場合authorize()メソッドを削除してしまっても良いそうです!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel8 User :: createのIDを取得し、そのIDを使用して新しい行を挿入した。(メモ)

AuthのRegisterControllerのcreateメソッドをこのように書き換えて、ユーザーの新規登録処理の直後にその登録されたユーザーの詳細データの行を挿入した。 protected function create(array $data) { $user = User::create([ //一旦、変数に入れる 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); userDetail::create([ //ここの処理を追加した 'userId' => $user->id, ]); return $user; //変数を返す }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel - デフォルトのユーザー登録に処理を追加する【初心者向け・備忘録】

※まだEloquentの使い方に慣れていない方に向けた内容です。 Laravelのデフォルト機能で作成できるregisterControllerで、ユーザを作成する際に何かしらの処理を追加する方法です。 createメソッド内の User::create([ 'name' => $data['name']...) を一度変数に格納し、 例 : $user = User::create... その後、登録時に行いたい処理を記載したら return $user; を返します。 ※登録処理自体に変更を加えたい場合は、registerControllerで public function register(Request $request) をオーバーライドしてあげましょう。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

未経験者が実際に出された技術課題

私が転職活動をする中で、面接後に実際に出された技術課題をまとめてみました。 言語の指定はありませんでした。 この記事にあるコードは私の回答例であって、 企業様がどのように評価されたかはわかりませんので、ご了承ください。 税抜き価格から税込の価格を計算し、それを出力するプログラムの作成 これは簡単!と思ったら、最後に 「必ず関数を使ってください」 の表記があり、一瞬焦りましたがたぶんできた。。 function taxIncluded($price,$tax){ return ($price * $tax) + $price; } echo taxIncluded(100,0.08); 繰り返し文と関数を利用して、3段階評価をするプログラムの作成 テストの点数からA・B・Cの3段階の成績をつけるプログラム ・80点以上をA ・80点未満、40点以上をB ・40点未満をC ・生徒5人の点数を定義して、5人分の成績を出力 ・繰り返し文と関数を利用 function grades($points) { foreach($points as $point){ if($point >= 80){ echo 'A'; } elseif($point < 80 && $point >=40){ echo 'B'; } else { echo 'C'; } } } grades([85,80,50,40,20]); ポートフォリオに追加したい機能の実装 面接の時に、 「このポートフォリオに追加実装したい機能はありますか?」と聞かれたため、 「はい!3つほど実装したい機能がありまして〜〜〜〜〜。」 といった感じで面接を終え、後日メールにて 「面接でおっしゃっていた追加機能の実装を元に再選考します。」 と、連絡が入りすぐに実装に取り掛かりました。 そして、いいね機能やWebAPIを使用した機能などなど、4つの機能を実装しました。 期限がない課題は、クオリティを求めるべきか、なるべく早く提出するべきか悩みますね。 私は、なるべく早い提出を心掛けました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerでlaravel環境を構築した際にMysqlに接続拒否された話

Dockerは起動済み appコンテナ内でマイグレーションを行おうとすると下記のエラーが出る。 Illuminate\Database\QueryExceptionSQLSTATE[HY000] [1045] Access denied for user 'test'@'172.19.0.2' (using password: YES) (SQL: select count(*) as aggregate from `articles`) 結論 docker-compose down --volumes docker-compose build docker-compose up -d このコマンドで Access denied for user 'test'@'172.19.0.2' (using password: YES) 部分のエラーは解決 後半のエラー部分は .env (laravelの) DB_PORT=3306 docker-compose.yml ports: - '4306:3306' 上記のようにすることで解決。 元々は.envファイルの中のDB_PORTが4306になっていたので3306に修正。 docker-compose.ymlをいじったらコンテナの起動をし直すことを忘れずに。 考えられる原因 前半部分 docker-compose down --volumes このコマンドはコンテナ・イメージ・ボリューム・ネットワーク・未定義コンテナを全てを一括消去するコマンドなので何か履歴が残っていたことが原因? 後半部分 DBに接続する際のport番号の認識が誤っていたことが原因。 .envのport番号とdocker-compose.ymlの右側のport番号がコンテナのport番号に対応(同じにする) docker-compose.ymlの左側のport番号はホストのport番号(Mk-2やSequel Proに接続する際に入力するport番号はこっち)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelの@jsonディレクティブには変数以外を入れてはいけない

概要 〜ある日の午後の出来事〜 web.php Route::get('hoge/{id}', 'HogeController@index')->name('hoge'); Route::get('fuga/{id}', 'FugaController@index')->name('fuga'); Laravel × Vue.jsでの開発中、このようなルートを設定して <div id="app"> <hogehuga :routes='@json([ "hoge" => route("hoge", 1), "fuga" => route("fuga" ,1), ])' > </hogefuga> </div> BladeテンプレートからVue.jsにルートを渡してみたところ 構文エラー え???と思い、実際のコードを見てみると・・・ なぜか、fugaの方のルートがパラメータ渡せていない & 配列やjson_encodeの閉じかっこが無い。。。 解決策 色々試してみても全く解決しそうになく、類似の事象もみつからない。このまま迷宮入りかと思いきや、ReadDoubleにこんな記述がありました。 Note: @jsonディレクティブは既存の変数をJSONとしてレンダするためだけに使用してください。Bladeテンプレートは正規表現ベースのため、複雑な式をディレクティブに渡すと予期しない不良動作の原因になります。 なるほどー。 今回のように@jsonディレクティブにroute関数などを使った複雑な式を直接入れると思わぬバグをうむ可能性があるみたい。 ということで、以下のようにして解決。 @php $routes = [ "hoge" => route("hoge", 1), "fuga" => route("fuga" ,1), ]; @endphp <div id="app"> <hogehuga :routes='@json($routes)' > </hogefuga> </div> @jsonディレクティブには変数以外を入れないように気をつけましょう。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【ギリ初心者向け】Laravel Docker AWS(EC2) Webアプリ(PHP)を0から簡単にデプロイする方法(無料)③ ーEC2にデプロイ編ー

0.概要  何度もいいますが、知らない単語が出た瞬間ググってください!!!!! ①の全体像編がこちらにあるのでこちらを一読してからだと理解がスムーズかと!!! https://qiita.com/SG_Sg/items/6b8ce48567b6b6602805  ②のDocker環境構築編もあるのでこちらでデプロイするアプリを作成してます https://qiita.com/SG_Sg/items/6b8ce48567b6b6602805 今回で作成するは具体的にいうと赤いとこ 以上が完成すると、世の中にアプリを公開することができます! つまり 特定のURLを叩くと誰でも作成したWebアプリを動かせる状態 ⇦目指すはここ AWSのEC2インスタンスを利用してデプロイを行うための流れ AWS?EC2インスタンス?とはなんですか?? AWS EC2インスタンスとは、Amazonが提供している仮想サーバー構築サービスです。。。。難しいですかね。 ざっくり言うと よくサーバーってなんかでかい四角い箱のイメージですが、AWSのEC2インスタンスはそれをクラウド上に作れる!! (EC2インスタンスとは OSを載せた仮想サーバーです) まあ概念的なものはおいといて手を動かしましょう。 上の図を完成させるための流れを説明します。 ①AWSにアカウントを作成する。 ②EC2インスタンスを作成する ③EC2インスタンスにSSHでアクセス ④EC2インスタンス(Ubuntu)に必要なアプリケーションをインストール ⑤GitHubからプロジェクト(ソースコード)をPULL ⑥Laravelをインストールしてのトップ画面を表示 ⑦データベースと接続 ⑧URLを叩いてアクセス!! 上の7つ行えば完了です! さあやっていきましょう! ①AWSにアカウントを作成する さて、AWSのアカウントを作成するのですが、、、 以下公式 https://aws.amazon.com/jp/register-flow/ わかりやすそうな動画つきのサイト https://blog.serverworks.co.jp/tech/2020/07/17/hajimeteno_aws_account/ 今回はAWSのEC2インスタンスというサービスを使うので、1年間は基本的にお金がかかりません! 利用サービスによっては一部料金をとられたりしますのでご注意ください。 https://www.fenet.jp/aws/column/aws-beginner/197/ 上記を参考に設定してもらえればお金はかからないことがわかります。 以上の操作でアカウントが作成し、TOP画面にきたら右上がこちらは東京(日本)にしてあることを必ず確認してください! ヨーロッパ等になっていたらかならずタップして アジアパシフィック「東京」 にするようにお願いします。 ②EC2インスタンスを作成する 1,サービスをタップし、EC2をタップ。 2,インスタンスをタップ 3,EC2インスタンス一覧が表示されたらインスタンスを起動をタップ 4,今回は Ubuntu Server 20.04 LTS (HVM), SSD Volume Type - ami-059b6d3840b03d6dd (64 ビット x86) を使いますのでこれを選択。(無料枠対象でUbuntuを使います。) 5,インスタンスタイプの設定。ここでインスタンスの容量を設定。今回は無料枠で行うので無料枠のt2.microを使います。 そして次のステップ:インスタンスの詳細の設定をタップ (ここからの設定はあとで変更できるので確認と作成でもいいですが、先に設定しちゃいましょう!!) 6,詳細にネットワークの設定をできますが、今回はこちらデフォルト(そのまま)で次のステップ:ストレージの追加をタップ 7,こちらでストレージサイズをいじれますが、今回はこちらもデフォルト(そのまま)で次のステップ:タグの追加をタップ 8,タグを追加できますが、今回は追加せずそのままで次のステップ:セキュリティグループの設定をタップ 9,セキュリティグループを設定します。 新しいセキュリティグループを作成する。にしてグループ名説明は自分でわかるように設定。 ルールの追加をタップして タイプは以下のように追加してください。 ※SSHの部分のポート範囲をマイIPしていますが、こちらは自分IPを使って接続しますよーの意味です。 そのため、自分のIPがコロコロ変わるWifi回線を使っている方は利用するたびにSSHのポート範囲を変えなければいけませんのでご注意!! もし不安でしたら今回はテストですので SSHのソースを 任意の場所 にして 0.0.0.0/0, ::/0 で良いと思います。 入力し終わったら確認と作成をタップ! 10,作成の確認画面がでますが、そのまま「起動」ボタンを押しましょう! 11,キーファイルを作成します。まずはプルダウンを 新しいキーペアの作成  キーペア名は任意ですが「HelloLaravel」とします 次にキーペアのダウンロードをタップ  ダウンロードされた「HelloLaravel.pem」をデスクトップにおいておきます。鍵の場所は必ずわかるようにしておいてください。  ※このダウンロードされたキーファイルはその名も通り、このインスタンスの中に入るための鍵なので無くさないように大切に保存しましょう。  今回はデスクトップにおきますが、本当は/.sshフォルダの中にあるとよいですね! 鍵ファイルをダウンロードできたら、インスタンスの作成 をタップ! 12,これでインスタンスを作成できたので インスタンスの表示 で開くなど3のインスタンス一覧まで戻りましょう。 そして、インスタンスが作成してから動かせるようになるまで少し時間がかかるので少々おまちください。 数分たったらこんな風になっていればOKです! ステータスチェックが2/2になっていることを確認してください! これでインスタンスの作成が完了です!! ③EC2インスタンスにSSHでアクセス 1,ターミナル(端末)を開いて、権限を変更し、SSHでアクセスする。 ターミナルを開き、ホームディレクトリ(最初の階層)で 先ほど保存した、鍵ファイルの権限を変えます(これをしないと接続できません) //鍵ファイルの権限を読み取りもできるように変更 ~ chmod 600 ~/Desktop/HelloLaravel.pem //鍵ファイルで作成したインスタンスにSSHでログイン ~ ssh -i ~/Desktop/HelloLaravel.pem ubuntu@(EC2インスタンスのパブリックIPアドレス) ※(EC2インスタンスのパブリックIPアドレス)これは↓の赤枠の部分に書いてある数字です。赤枠の左の部分の四角いマークをタップすればコピーできます ↓こうなっていたらアクセス完了です! ubuntu@ip-自分のIP:~$ ④EC2インスタンス(Ubuntu)に必要なアプリケーションをインストール 1,php7.4をインストール //パッケージの更新 ubuntu@ip-自分のIP:~$ sudo apt-get update //PHP PPA Repositoryを追加 ubuntu@ip-自分のIP:~$ sudo apt -y install software-properties-common ubuntu@ip-自分のIP:~$ sudo add-apt-repository ppa:ondrej/php ubuntu@ip-自分のIP:~$ sudo apt-get update //PHPインストール ubuntu@ip-自分のIP:~$ sudo apt -y install php7.4 //バージョン確認 ubuntu@ip-自分のIP:~$ php -v PHP 7.4.16 (cli) (built: Mar 5 2021 07:54:38) ( NTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies with Zend OPcache v7.4.16, Copyright (c), by Zend Technologies 2,MySQL 8.0をインストール //パッケージの更新 ubuntu@ip-自分のIP:~$ sudo apt update //mysqlインストール ubuntu@ip-自分のIP:~$ sudo apt install -y mysql-server //mysqlを動かす ubuntu@ip-自分のIP:~$ sudo service mysql start //バージョン確認 ubuntu@ip-自分のIP:~$ sudo mysql -u root -e'select version();' +-------------------------+ | version() | +-------------------------+ | 8.0.23-0ubuntu0.20.04.1 | +-------------------------+ 3,nginx1.18をインストール //パッケージの更新 ubuntu@ip-自分のIP:~$ sudo apt update //nginxをインストール ubuntu@ip-自分のIP:~$ sudo apt install -y nginx //場所を確認 ubuntu@ip-自分のIP:~$ sudo which nginx /usr/sbin/nginx //バージョン確認 ubuntu@ip-自分のIP:~$ nginx -v nginx version: nginx/1.18.0 (Ubuntu) nginxが動いているのかの確認 ubuntu@ip-自分のIP:~$ sudo service nginx start ubuntu@ip-自分のIP:~$ sudo service nginx status ● nginx.service - A high performance web server and a reverse proxy server Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset:>    //↓がactiveになってたらOK。 Active: active (running) since Sun 2021-04-11 06:44:04 UTC; 1s ago Docs: man:nginx(8) ・・・・・・ //Failになっていたらポートが占領されていたりするので ubuntu@ip-自分のIP:~$ sudo lsof -i:80 //確認して一度占領ポートを全部消す。数字は↑で確認した番号 ubuntu@ip-自分のIP:~$ sudo kill 23930 23933 23934 23935 23936 23937 25159 http://(EC2インスタンスのパブリックIPアドレス)/index をgoogleでアクセス!notfoundでnginxが動いていることを確認 ※番外 HTMLファイルをテストで表示 ubuntu@ip-自分のIP:/var/www$ ls html ubuntu@ip-自分のIP:/var/www$ cd html/ ubuntu@ip-自分のIP:/var/www/html$ vi test.html ↓test.htmlを作成 <html> <body>HTMLTEST</body> </html> http://(EC2インスタンスのパブリックIPアドレス)/test.html をgoogleでアクセス! HTMLTESTが表示されていたらnginxでHTMLが表示できていることを確認できる。 ④php7.4-fpmをインストールする ubuntu@ip-自分のIP:~$ sudo apt update //php-fpmをインストール ubuntu@ip-自分のIP:~$ sudo apt install php7.4-fpm //バージョンを確認 ubuntu@ip-自分のIP:~$ php-fpm7.4 -v PHP 7.4.16 (fpm-fcgi) (built: Mar 5 2021 07:54:38) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies with Zend OPcache v7.4.16, Copyright (c), by Zend Technologies ⑤GitHubからプロジェクト(ソースコード)をクローン ubuntu@ip-自分のIP:/var/www$ sudo git clone https://github.com/K-SG/DockerLaravelTestProject.git Cloning into 'DockerLaravelTestProject'... remote: Enumerating objects: 164, done. remote: Counting objects: 100% (164/164), done. remote: Compressing objects: 100% (119/119), done. remote: Total 164 (delta 25), reused 157 (delta 18), pack-reused 0 Receiving objects: 100% (164/164), 72.99 KiB | 7.30 MiB/s, done. Resolving deltas: 100% (25/25), done. //確認 ubuntu@ip-自分のIP:/var/www$ ls DockerLaravelTestProject html //プロジェクトの権限をwww-dataに変更 ubuntu@ip-自分のIP:/var/www$ sudo chown -R www-data:www-data DockerLaravelTestProject/ ubuntu@ip-172-31-35-119:/var/www$ ls -al total 16 drwxr-xr-x 4 root root 4096 Apr 18 06:04 . drwxr-xr-x 14 root root 4096 Apr 18 05:51 .. drwxr-xr-x 5 www-data www-data 4096 Apr 18 06:04 DockerLaravelTestProject drwxr-xr-x 2 root root 4096 Apr 18 06:12 html ⑥nginxの設定を変えて、phpファイルが表示できることを確認 1,nginxの設定ファイルを変える ubuntu@ip-自分のIP:/var/www$ cd /etc/nginx/sites-enabled/ ubuntu@ip-自分のIP:/etc/nginx/sites-enabled$ sudo vi default 以下に変更する。 server { listen 80 default_server; listen [::]:80 default_server; # SSL configuration # # listen 443 ssl default_server; # listen [::]:443 ssl default_server; # # Note: You should disable gzip for SSL traffic. # See: https://bugs.debian.org/773332 # # Read up on ssl_ciphers to ensure a secure configuration. # See: https://bugs.debian.org/765782 # # Self signed certs generated by the ssl-cert package # Don't use them in a production server! # # include snippets/snakeoil.conf; root /var/www/DockerLaravelTestProject/backend/public; # Add index.php to the list if you are using PHP       index index.html index.htm index.nginx-debian.html index.php; server_name _; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. # try_files $uri $uri/ =404; try_files $uri $uri/ /index.php?$query_string; } # pass PHP scripts to FastCGI server # location ~ \.php$ { include snippets/fastcgi-php.conf; # # # With php-fpm (or other unix sockets): fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; # # With php-cgi (or other tcp sockets): # fastcgi_pass 127.0.0.1:9000; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; fastcgi_split_path_info ^(.+\.php)(.*)$; fastcgi_param PATH_INFO $fastcgi_path_info; include fastcgi_params; } # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} } ※設定ファイルを変更(↑のように)、サーバーがうまく動作していない場合はnginxを必ず再起動 ubuntu@ip-自分のIP:~$ sudo service nginx stop ubuntu@ip-自分のIP:~$ sudo service nginx start //状態を確認 ubuntu@ip-自分のIP:~$ sudo service nginx status 2,プロジェクトにPHPファイルを作って接続を確認する。 //プロジェクトの中のpublicまで移動 ubuntu@ip-自分のIP:/var/www/DockerLaravelTestProject/backend/public$ ls favicon.ico index.php robots.txt web.config ubuntu@ip-自分のIP:/var/www/DockerLaravelTestProject/backend/public$ sudo vi phpinfo.php ↓で保存phpinfo.phpを作成 <?php phpinfo(); ?> http://(EC2インスタンスのパブリックIPアドレス)/phpinfo.php をgoogleでアクセス! PHPの情報が表示されていたらnginxでPHPのファイルがが表示できていることを確認できる。 3,現状足りていないPHPに必要なものをインストール ubuntu@ip-自分のIP:/var/www/DockerLaravelTestProject/backend$ sudo apt install php7.4-mbstring php-xml php-json ⑦LaravelをインストールしてWelcome画面表示する 1,Laravelをインストール //コンポーザーをインストール。(ここでエラーが出る場合、PHPに必要なものが入っていないのでググってインストールしよう!) ubuntu@ip-自分のIP:/var/www/DockerLaravelTestProject/backend$ sudo composer install //composer install 時は .env 環境変数ファイルは作成されないので、 .env.example を元にコピーして作成します ubuntu@ip-自分のIP:/var/www/DockerLaravelTestProject/backend$ sudo cp .env.example .env ubuntu@ip-自分のIP:/var/www/DockerLaravelTestProject/backend$ cd ../ //backend以下の権限がないため権限を変更する ubuntu@ip-自分のIP:/var/www/DockerLaravelTestProject$ sudo chmod 777 -R backend/ ubuntu@ip-自分のIP:/var/www/DockerLaravelTestProject$ cd backend/ //アプリケーションキーを生成する ubuntu@ip-自分のIP:/var/www/DockerLaravelTestProject/backend$ php artisan key:generate Application key set successfully. //APP_KEY=base64:bfeLkhwqXIFbGtwhaJOp0TpfHTJD3Q+SRi7lVwB・・・・となっていることを確認。 2,welcome画面を表示する http://(EC2インスタンスのパブリックIPアドレス) をgoogleでアクセス! ↑のようなものが表示されたらOK!! ⑧データベースを作成する ※【ギリ初心者向け】Laravel Docker AWS(EC2) Webアプリ(PHP)を0から簡単にデプロイする方法(無料) ②で作成した合わせるのでファイルをみながらすすめます。 1,mysqlにログインしてユーザーを作成する。 ubuntu@ip-自分のIP:/var/www/DockerLaravelTestProject/backend$ sudo mysql -u root -p //PWを求められますがrootユーザーはMACに入るときのPW を入力 Enter password: ・・・・・・ //mysqlに入れたことを確認 mysql> 2,プロジェクトの.envファイルをみながらユーザー、DBを作成する! その前にプロジェクトの.envファイルのDBの部分をみる DB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 DB_DATABASE=sg_db DB_USERNAME=sg DB_PASSWORD=sg //sgというdbユーザーを作成。PWはsg mysql> create user 'sg'@'localhost' identified by 'sg'; Query OK, 0 rows affected (0.01 sec) //databaseを作る権限をsgユーザーに付与する mysql> GRANT ALL ON sg_db.* TO 'sg'@'localhost'; Query OK, 0 rows affected (0.00 sec) //mysqlからでる mysql> exit; Bye ubuntu@ip-自分のIP:~$ sudo mysql -u sg -p //PWはさっき設定したsg Enter password: //データベースを作成する mysql> create database sg_db; Query OK, 1 row affected (0.01 sec)w mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | sg_db | +--------------------+ //抜ける mysql> exit; Bye 3,テーブルを作るためにマイグレーションを実行する! まずはマイグレーションを実行するために、mysqlに接続できるように設定を変更する。 ※マイグレーションがうまくいかなかったら都度ググりましょう!結構うまくいかないパターンはあります。。キャッシュがたまっていたり。。。 ubuntu@ip-自分のIP:/var/www/DockerLaravelTestProject/backend$ sudo vi .env //DBの部分を↓に変更。HOSTはlocalhost DB_CONNECTION=mysql DB_HOST=localhost DB_PORT=3306 DB_DATABASE=sg_db DB_USERNAME=sg DB_PASSWORD=sg ubuntu@ip-自分のIP:/var/www/DockerLaravelTestProject/backend$ sudo php artisan migrate Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (65.08ms) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (55.04ms) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (59.14ms) Migrating: 2021_01_03_090902_create_people_table Migrated: 2021_01_03_090902_create_people_table (31.46ms) //マイグレーションできたらデータベースの中にテーブルが作られていることを確認すると良い //この流れでSeederも入れてしまおう。 ubuntu@ip-自分のIP:/var/www/DockerLaravelTestProject/backend$ php artisan db:seed Seeding: Database\Seeders\PeopleTableSeeder Seeded: Database\Seeders\PeopleTableSeeder (11.62ms) Database seeding completed successfully. 4,アプリを表示して接続を確認! http://(EC2インスタンスのパブリックIPアドレス)/hello これにて終了です。 お疲れ様でした。 これでLaravelアプリをEC2にデプロイすることができました!!ここのDBとかをmysqlworkbenchとかで管理できたら良いですね!! それでは良いWebアプリ制作ライフを!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】@csrf ←コイツの存在について

はじめに 現場では主にモバイルアプリ開発(React Native, TypeScript)を行っているのですが、WEBアプリ開発(Laravel)にも3割くらい携わっています。 これまでなんとなくやってこれたのですが、振り返ってみるとよく理解せずに実装してきたところがいろいろありました。 例えば、タイトルの@csrfなどformを書く際のおまじない的な感じで書いてきましたが、何のための記述なのかよくわかっていませんでした。 言語のスキルをいくら高めてようとしても、基礎理解がおろそかなままだとレベルの上限があります。 ということで、これまで理解がふわふわだったところを一個ずつまとめていくことにしました。 この記事の対象読者 CSRFについて知りたい方 Laravelの@csrfが何を行っているのかを知りたい方 Cross Site Request Forgery (CSRF) Cross Site Request Forgery(CSRF)は、WEBアプリケーションが偽装されたリクエストを正規のものとして受信してしまう脆弱性、または攻撃手法を意味します。 例えば、とあるWEBアプリでパスワードを変更するためのフォームがあったとします。 CSRFの対策がされていないと、以下の流れでそのアプリにログインするためのパスワードが書き換えられてしまう恐れがあります。 見知らぬリンクが記載されたメールが送られてくる メールを開いてリンクをクリックしてしまう リンクにパスワード変更のフォームが組み込まれており、WEBアプリにリクエストが送られてしまう WEBアプリのログインパスワードが変更されてしまう ユーザの気が付かないうちに偽装されて送信されたパスワード更新のリクエストが、そのままWEBアプリ側で受け付けてしまうのが問題だということですね。 つまり、CSRF対策というのは、このようなリクエストがブロックされるような仕組みをつくることと同義ということになります。 @csrfって何? @csrfというのは、CSRFトークンを利用したLaravelにおけるCSRF対策の一つです。 Laravelでは、アプリケーションによって管理されているアクティブなユーザーの各セッションごとに、CSRFトークンを自動的に生成します。 @csrfをformに加えることで、リクエストが送信されたときにCSRFトークンが生成され、セッションに保存されたトークンと一致するかどうかをVerifyCsrfTokenミドルウェアが確認してくれます。 トークンが一致しない場合にはリクエストをブロックするため、このようにして悪意のあるリクエストからアプリを守ってくれるようになっています。 <form method="POST" action="{{ route('login') }}"> @csrf //CSRFトークンを付与 ... </form> おわりに これからLaravelのアウトプットもやっていきます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelでページネーション実装

前提 PHP Laravel 7.1.19 5.6.27 使用方法 LaravelのペジネータはクエリビルダとEloquent ORMに統合されている。 今回はpagenateメソッドを用いることとする。 クエリビルダ 下記のように、paginateに一つだけ引数を渡しており、今回はページごとに10アイテムを表示するように指定している。 <?php namespace App\Http\Controllers; use Illuminate\Support\Facades\DB; use App\Http\Controllers\Controller; class UserController extends Controller { const PER_PAGE = 10; /** * アプリケーションの全ユーザー表示 * * @return Response */ public function index() { $users = DB::table('users')->paginate(self::PER_PAGE); return view('user.index', compact('users'); } } Eloquent Eloquentモデルも同様にpagenateメソッドを用いる。 $users = App\User::paginate(10); $users = User::where('name', '太郎')->paginate(10); $users = User::orderBy('created_at', 'desc')->paginate(10); ページネーション表示 pagenateメソッドはIlluminate\Pagination\LengthAwarePaginatorインスタンスを返すので 、その結果をBladeに渡して、結果を表示する。 {{ $users->appends(request()->query())->links() }} ・appends ペジネーションリンクにクエリ文字列を付加する。 クエリ文字列は「https:// ○△×□.jp/?hoge=hogehoge」の「?hoge=hogehoge」の部分 ・request 現在のリクエストインスタンス(Illuminate\Http\Request)を返す。 ・query request()->query()でクエリ文字列を取得する。 ・links  検索結果の残りのページヘのリンクを付加する。各リンクにはpageクエリ文字列変数が含まれている。 参考 https://readouble.com/laravel/5.8/ja/pagination.html
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LaravelのチュートリアルとしてTodoアプリを作成していく。~Part4~

はじめに 私はプログラミング歴1年の初心者です。 実務でWebサイトのコーディングを1年間行ってきました。 そろそろシステム開発もできるようになりたいということで LaravelやReactをこれから勉強していこうと思っております。 この記事の目的 Laravelのチュートリアルを進めて行く中で Laravelの主要な仕組みを理解することです。 この記事は前回の記事があるので、もしご覧になっていない方がいればこちらからどうぞ。 参考記事(チュートリアル記事) こちらのTodoアプリを作成するチュートリアル記事を参考にさせていただきました。 すごく丁寧に説明してくださっているのですごく勉強になりました。 目次 (1)開発環境 (2)アプリケーション設計 (3)プロジェクト作成 (4)一覧機能 (5)作成機能 (6)編集機能 ↓今回はここから(認証機能の後半から)↓ (7)認証機能 (8)エラーハンドリング (9)デプロイ 認証機能(後半戦!) ヘッダーの出し分け ポイントは ○Auth::check()はログインしていればtrue、してなければfalseを返すこと。 ※Auth::guest()という逆の働きをするメソッドもある。 ○Auth::user()でログインしているユーザーを取得できる。 ○今回のログアウトはでやりたかったので、JSを使って実装。 layout.blade.php // headerの中身を変更する 変更前 <nav class="my-navbar"> <a class="my-navbar-brand" href="/">ToDo App</a> </nav> ↓↓↓↓↓↓↓↓↓ 変更後 <nav class="my-navbar"> <a class="my-navbar-brand" href="/">ToDo App</a> <div class="my-navbar-control"> @if(Auth::check()) <span class="my-navbar-item">ようこそ, {{ Auth::user()->name }}さん</span> | <a href="#" id="logout" class="my-navbar-item">ログアウト</a> <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;"> @csrf </form> @else <a class="my-navbar-item" href="{{ route('login') }}">ログイン</a> | <a class="my-navbar-item" href="{{ route('register') }}">会員登録</a> @endif </div> </nav> layout.blade.php // main下を変更する 変更前 <main> @yield('content') </main> @yield('scripts') </body> </html> ↓↓↓↓↓↓↓↓↓ 変更後 <main> @yield('content') </main> @if(Auth::check()) <script> document.getElementById('logout').addEventListener('click', function(event) { event.preventDefault(); document.getElementById('logout-form').submit(); }); </script> @endif @yield('scripts') </body> </html> ミドルウェアを使ってページに認証を求める ポイントは ○ミドルウェアはルーティングごとに移る前に実行されるプログラムのこと。 ○認証状態の確認というのは、各ルートに共通した確認事項なので、こちらで実装しましょうということ。 Routingの設定 ポイントは ○Route::group()の記述でRoutingをまとめること。 ○認証ミドルウェアの'auth'の記述は、Kernel.phpにある。 ○'auth'というのは、ログインしていたら中のRoutingに進み、ログインしていなかったらログイン画面にリダイレクトさせるもの。 web.php Route::group(['middleware' => 'auth'], function() { Route::get('/', 'App\Http\Controllers\HomeController@index')->name('home'); Route::get('/folders/{id}/tasks', 'App\Http\Controllers\TaskController@index')->name('tasks.index'); Route::get('/folders/create', 'App\Http\Controllers\FolderController@showCreateForm')->name('folders.create'); Route::post('/folders/create', 'App\Http\Controllers\FolderController@create'); Route::get('/folders/{id}/tasks/create', 'App\Http\Controllers\TaskController@showCreateForm')->name('tasks.create'); Route::post('/folders/{id}/tasks/create', 'App\Http\Controllers\TaskController@create'); Route::get('/folders/{id}/tasks/{task_id}/edit', 'App\Http\Controllers\TaskController@showEditForm')->name('tasks.edit'); Route::post('/folders/{id}/tasks/{task_id}/edit', 'App\Http\Controllers\TaskController@edit'); }); Auth::routes(); ミドルウェアを編集して、ログイン前のみ閲覧出来るページを探す ポイントは ○redirect先をRouteServiceProvider::HOMEから'/'にすること。 ○認証ミドルウェアの'guest'の記述は、Kernel.phpにある。 ○RedirectIfAuthenticatedはRegisterController.phpやLoginController.phpのコンストラクタで適用されている。 app/Http/Middlware/RedirectIfAuthenticated.php public function handle($request, Closure $next, $guard = null) { if (Auth::guard($guard)->check()) { return redirect('/'); // ★ 引数を変更 } return $next($request); } コントローラーでログインユーザーに紐付いたフォルダを作成できるようにする ポイントは ○Auth::user()でログインユーザーモデルを取得していること。 ○リレーションを利用してフォルダモデルを保存している。 FolderController.php // ★ Authクラスをインポートする use Illuminate\Support\Facades\Auth; class FolderController extends Controller { // 中略 public function create(CreateFolder $request) { // フォルダモデルのインスタンスを作成する $folder = new Folder(); // タイトルに入力値を代入する $folder->title = $request->title; // ★ ユーザーに紐づけて保存 Auth::user()->folders()->save($folder); // 以下略 コントローラーでログインユーザーとしてタスクを表示できるようにする ポイントは ○上記と同じ TaskController.php // ★ Authクラスをインポートする use Illuminate\Support\Facades\Auth; class TaskController extends Controller { public function index(int $id) { // ★ ユーザーのフォルダを取得する $folders = Auth::user()->folders()->get(); // 以下略 フォルダを作成済みであればログイン後にタスク一覧にリダイレクト ポイントは ○HomeController.phpで設定すること HomeCotroller.php // 以下を追記 use Illuminate\Support\Facades\Auth; public function index() { // ログインユーザーを取得する $user = Auth::user(); // ログインユーザーに紐づくフォルダを一つ取得する $folder = $user->folders()->first(); // まだ一つもフォルダを作っていなければホームページをレスポンスする if (is_null($folder)) { return view('home'); } // フォルダがあればそのフォルダのタスク一覧にリダイレクトする return redirect()->route('tasks.index', [ 'id' => $folder->id, ]); } パスワード再設定機能 ポイントは ○パスワード再設定のために必要なメールをMailtrapというサービスを使って実現すること。 ○.envで設定すること。 ○auth/passwords/email.blade.phpの編集。 // MailtrapのLaravel対応の設定をする(Demo inboxのSMTP設定から確認できる) MAIL_MAILER=smtp MAIL_HOST=smtp.mailtrap.io MAIL_PORT=2525 MAIL_USERNAME=USERNAME MAIL_PASSWORD=PASSWORD MAIL_ENCRYPTION=ENCRYPTION MAIL_FROM_ADDRESS=todoapp2@email.com MAIL_FROM_NAME="todoapp2" auth/passwords/email.blade.php // パスワード再設定メール送信ページ @extends('layout') @section('content') <div class="container"> <div class="row"> <div class="col col-md-offset-3 col-md-6"> <nav class="panel panel-default"> <div class="panel-heading">パスワード再発行</div> <div class="panel-body"> @if (session('status')) <div class="alert alert-success" role="alert"> {{ session('status') }} </div> @endif <form action="{{ route('password.email') }}" method="POST"> @csrf <div class="form-group"> <label for="email">メールアドレス</label> <input type="text" class="form-control" id="email" name="email" /> </div> <div class="text-right"> <button type="submit" class="btn btn-primary">再発行リンクを送る</button> </div> </form> </div> </nav> </div> </div> </div> @endsection auth/passwords/reset.blade.php // パスワード再設定ページ @extends('layout') @section('content') <div class="container"> <div class="row"> <div class="col col-md-offset-3 col-md-6"> <nav class="panel panel-default"> <div class="panel-heading">パスワード再発行</div> <div class="panel-body"> <form action="{{ route('password.update') }}" method="POST"> @csrf <input type="hidden" name="token" value="{{ $token }}"> <div class="form-group"> <label for="email">メールアドレス</label> <input type="text" class="form-control" id="email" name="email" required autocomplete="email" autofocus/> </div> <div class="form-group"> <label for="password">新しいパスワード</label> <input type="password" class="form-control" id="password" name="password" required autocomplete="new-password"/> </div> <div class="form-group"> <label for="password-confirm">新しいパスワード(確認)</label> <input type="password" class="form-control" id="password-confirm" name="password_confirmation" required autocomplete="new-password"/> </div> <div class="text-right"> <button type="submit" class="btn btn-primary">送信</button> </div> </form> </div> </nav> </div> </div> </div> @endsection Auth/ResetPasswordController.php protected $redirectTo = '/'; メッセージの日本語化 ポイントは ○ForgotPasswordController.phpとResetPasswordController.phpのどちらも修正する方法ではなく、validation.phpで一括で変更している点。(アプリ全体に反映される) ○lang/ja/passwords.phpを編集する。 lang/ja/validation.php // 以下を追記 'attributes' => [ 'email' => 'メールアドレス', 'password' => 'パスワード', 'token' => 'トークン', ], $ cp ./resources/lang/en/passwords.php ./resources/lang/ja/ lang/ja/passwords.php // 以下を編集 'reset' => 'パスワードを再設定しました。', 'sent' => 'パスワード再設定リンクを送信しました。', 'token' => 'トークンが無効です。', 'user' => "入力されたメールアドレスのユーザーは見つかりませんでした。", メールの内容を変更する ポイントは ○メールの内容はresources/views/mail/password-reset.blade.phpで編集できること。 ○Mailableクラスがメールの送信を司ること。 ○subject()メソッドは件名を決めるメソッド。 ○Userモデルにパスワード再設定メールの設定をする。 ○ちなみにtokenは2014_10_12_100000_create_password_resets_table.phpを見ると、ちゃんと、tokenのカラムがあることがわかる。 詳しくは以下を参照にしてください。 // resources/views/mail/password-reset.blade.phpを作成する $ mkdir resources/views/mail $ touch resources/views/mail/password-reset.blade.php resources/views/mail/password-reset.blade.php <a href="{{ route('password.reset', ['token' => $token]) }}"> パスワード再設定リンク </a> // Mailableクラスの雛形を作成する $ php artisan make:mail ResetPassword app/Mail/ResetPassword.php 変更前 <?php namespace App\Mail; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; class ResetPassword 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->view('view.name'); } } ↓↓↓↓↓↓↓↓↓↓ 変更後 <?php namespace App\Mail; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; class ResetPassword extends Mailable { use Queueable, SerializesModels; public $token; /** * Create a new message instance. * * @return void */ public function __construct($token) { $this->token = $token; } /** * Build the message. * * @return $this */ public function build() { return $this->subject('パスワード再設定')->view('mail.password-reset'); } } app/Models/User.php use App\Mail\ResetPassword; // ★ 追加 use Illuminate\Support\Facades\Mail; // ★ 追加 class User extends Authenticatable { // 略 /** * ★ パスワード再設定メールを送信する */ public function sendPasswordResetNotification($token) { Mail::to($this)->send(new ResetPassword($token)); } // 略 } エラーハンドリング ポイントは ○エラーハンドリングとは、予期しないリクエストに対するエラーに対応することです。 ○レスポンスステータスコードがあるので、それぞれに適切なコードを選択するようにすること。 ○abort関数を使ってエラー系のレスポンスを返却すること。(練習) ○ルートモデルバインディングを使って、一連の流れをフレームワークに任せることができるようにする。 ○ルートとモデルを紐付けるのが、ルートモデルバインディング機能。 ○これによって、URL中のID部分に該当するフォルダデータがコントローラーに渡されるようになるので、abortしなくても自動で404エラー画面に遷移する。 存在しないフォルダIDにアクセスで404エラー(練習) TaskController.php // 存在しないフォルダIDにアクセスすると404が返される。 public function index(int $id) { // 略 // 選ばれたフォルダを取得する $current_folder = Folder::find($id); if (is_null($current_folder)) { abort(404); } // 略 } ルートモデルバインディングを使って、abortを使わずに処理する。 web.php // {id}から{folder}に変更する Route::get('/folders/{folder}/tasks', 'App\Http\Controllers\TaskController@index')->name('tasks.index'); TaskController.php // 以下のように編集する 変更前 public function index(int $id) { // ログインユーザーのフォルダを取得する $folders = Auth::user()->folders()->get(); // 選ばれたフォルダを取得する $current_folder = Folder::find($id); if(is_null($current_folder)) { abort(404); } // 選ばれたフォルダに紐づくタスクを取得する $tasks = $current_folder->tasks()->get(); return view('tasks/index', [ 'folders' => $folders, 'current_folder_id' => $current_folder->id, 'tasks' => $tasks, ]); } ↓↓↓↓↓↓↓↓↓↓ 変更後 public function index(Folder $folder) { // ログインユーザーのフォルダを取得する $folders = Auth::user()->folders()->get(); // 選ばれたフォルダに紐づくタスクを取得する $tasks = $folder->tasks()->get(); return view('tasks/index', [ 'folders' => $folders, 'current_folder_id' => $folder->id, 'tasks' => $tasks, ]); } タスクの作成と編集もルートモデルバインディング化する web.php // {id}から{folder}に、{task_id}から{task}に変更する Route::get('/folders/{folder}/tasks/create', 'App\Http\Controllers\TaskController@showCreateForm')->name('tasks.create'); Route::post('/folders/{folder}/tasks/create', 'App\Http\Controllers\TaskController@create'); Route::get('/folders/{folder}/tasks/{task}/edit', 'App\Http\Controllers\TaskController@showEditForm')->name('tasks.edit'); Route::post('/folders/{folder}/tasks/{task}/edit', 'App\Http\Controllers\TaskController@edit'); TaskController.php // createとedit関係を編集する 変更前 public function showCreateForm(int $id) { return view('tasks/create', [ 'folder_id' => $id, ]); } public function create(int $id, CreateTask $request) { $current_folder = Folder::find($id); $task = new Task(); $task->title = $request->title; $task->due_date = $request->due_date; $current_folder->tasks()->save($task); return redirect()->route('tasks.index', [ 'id' => $current_folder->id, ]); } /** * GET /folders/{id}/tasks/{task_id}/edit */ public function showEditForm(int $id, int $task_id) { $task = Task::find($task_id); return view('tasks/edit', [ 'task' => $task, ]); } public function edit(int $id, int $task_id, EditTask $request) { // リクエストされたIDのタスクデータを取得する $task = Task::find($task_id); // そのタスクデータに入力された値を代入する $task->title = $request->title; $task->status = $request->status; $task->due_date = $request->due_date; $task->save(); // 編集対象のタスクが属するタスク一覧画面にリダイレクトする return redirect()->route('tasks.index', [ 'id' => $task->folder_id, ]); } } ↓↓↓↓↓↓↓↓↓↓ 変更後 <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\Folder; use App\Models\Task; use App\Http\Requests\CreateTask; use App\Http\Requests\EditTask; use Illuminate\Support\Facades\Auth; class TaskController extends Controller { /** * タスク一覧 * @param Folder $folder * @return \Illuminate\View\View */ public function index(Folder $folder) { // ログインユーザーのフォルダを取得する $folders = Auth::user()->folders()->get(); // 選ばれたフォルダに紐づくタスクを取得する $tasks = $folder->tasks()->get(); return view('tasks/index', [ 'folders' => $folders, 'current_folder_id' => $folder->id, 'tasks' => $tasks, ]); } /** * タスク作成フォーム * @param Folder $folder * @return \Illuminate\View\View */ public function showCreateForm(Folder $folder) { return view('tasks/create', [ 'folder' => $folder->id, ]); } /** * タスク作成 * @param Folder $folder * @param CreateTask $request * @return \Illuminate\Http\RedirectResponse */ public function create(Folder $folder, CreateTask $request) { $task = new Task(); $task->title = $request->title; $task->due_date = $request->due_date; $folder->tasks()->save($task); return redirect()->route('tasks.index', [ 'folder' => $folder->id, ]); } /** * タスク編集フォーム * @param Folder $folder * @param Task $task * @return \Illuminate\View\View */ public function showEditForm(Folder $folder, Task $task) { return view('tasks/edit', [ 'task' => $task, ]); } /** * タスク編集 * @param Folder $folder * @param Task $task * @param EditTask $request * @return \Illuminate\Http\RedirectResponse */ public function edit(Folder $folder, Task $task, EditTask $request) { // そのタスクデータに入力された値を代入する $task->title = $request->title; $task->status = $request->status; $task->due_date = $request->due_date; $task->save(); // 編集対象のタスクが属するタスク一覧画面にリダイレクトする return redirect()->route('tasks.index', [ 'folder' => $task->folder_id, ]); } } Homeのルートモデルバインディング化する エラーがでてきたので、Homeコントローラーもやっておこう。 HomeController.php // idからfolderに編集する 変更前 public function index() { // ログインユーザーを取得する $user = Auth::user(); // ログインユーザーに紐づくフォルダを一つ取得する $folder = $user->folders()->first(); // まだ一つもフォルダを作っていなければホームページをレスポンスする if (is_null($folder)) { return view('home'); } // フォルダがあればそのフォルダのタスク一覧にリダイレクトする return redirect()->route('tasks.index', [ 'id' => $folder->id, ]); } ↓↓↓↓↓↓↓↓↓↓↓↓ 変更後 use App\Models\Folder; public function index(Folder $folder) { // ログインユーザーを取得する $user = Auth::user(); // ログインユーザーに紐づくフォルダを一つ取得する $folder = $user->folders()->first(); // まだ一つもフォルダを作っていなければホームページをレスポンスする if (is_null($folder)) { return view('home'); } // フォルダがあればそのフォルダのタスク一覧にリダイレクトする return redirect()->route('tasks.index', [ 'folder' => $folder->id, ]); } テンプレート内のリンクもルートバインディング化する エラーが出たので、テンプレートのリンクも修正しよう。 ポイントは ○おそらく最初からルートバインディングシていたほうが良さそう。 xxxxxx.blade.php // リンク指定の中の'id'を'folder'にする // リンク指定の中の'task_id'を'task'にする フォルダの作成についてもルートバインディング化する FolderController.php // 'id'を'folder'に変更する 権限がないコンテンツを403エラーで返す(練習) ポイントは ○権限がないコンテンツに関しては403エラーで返すこと。 ○この記述は一旦試したらけしておくこと。 TaskController.php // 403エラーで返す public function index(Folder $folder) { if (Auth::user()->id !== $folder->user_id) { abort(403); } // 以下略 } ポリシークラスを使って、abortを使わずに403エラーを表示する ポイントは ○ポリシークラスはLaravelでの認可処理を司ること。 ○このポリシークラスでの設定したviewメソッドは「ユーザーとフォルダが紐付いているときに認可する」という意味が定義される。 ○作成したポリシーはAuthServiceProviderに登録する。 ○Folderモデルに対する処理への認可にはFoderPolicyポリシーを使用するということ。 ○ミドルウェアを介してポリシーを使用する。 $ php artisan make:policy FolderPolicy app/Policies/FolderPolicy.php // 以下を追記 use App\Models\Folder; /** * フォルダの閲覧権限 * @param User $user * @param Folder $folder * @return bool */ public function view(User $user, Folder $folder) { return $user->id === $folder->user_id; } app/Http/Providers/AuthServiceProvider.php use App\Models\Folder; // 追加 use App\Policies\FolderPolicy; // 追加 protected $policies = [ Folder::class => FolderPolicy::class, ]; web.php // 以下の変更を加えて、ミドルウェアを適用させてポリシーを呼び出す。 Route::group(['middleware' => 'can:view,folder'], function() { Route::get('/folders/{folder}/tasks', 'App\Http\Controllers\TaskController@index')->name('tasks.index'); Route::get('/folders/{folder}/tasks/create', 'App\Http\Controllers\TaskController@showCreateForm')->name('tasks.create'); Route::post('/folders/{folder}/tasks/create', 'App\Http\Controllers\TaskController@create'); Route::get('/folders/{folder}/tasks/{task}/edit', 'App\Http\Controllers\TaskController@showEditForm')->name('tasks.edit'); Route::post('/folders/{folder}/tasks/{task}/edit', 'App\Http\Controllers\TaskController@edit'); }); (ちなみに全体の見た目は) Route::group(['middleware' => 'auth'], function() { Route::get('/', 'App\Http\Controllers\HomeController@index')->name('home'); Route::get('/folders/create', 'App\Http\Controllers\FolderController@showCreateForm')->name('folders.create'); Route::post('/folders/create', 'App\Http\Controllers\FolderController@create'); Route::group(['middleware' => 'can:view,folder'], function() { Route::get('/folders/{folder}/tasks', 'App\Http\Controllers\TaskController@index')->name('tasks.index'); Route::get('/folders/{folder}/tasks/create', 'App\Http\Controllers\TaskController@showCreateForm')->name('tasks.create'); Route::post('/folders/{folder}/tasks/create', 'App\Http\Controllers\TaskController@create'); Route::get('/folders/{folder}/tasks/{task}/edit', 'App\Http\Controllers\TaskController@showEditForm')->name('tasks.edit'); Route::post('/folders/{folder}/tasks/{task}/edit', 'App\Http\Controllers\TaskController@edit'); }); }); Auth::routes(); フォルダとタスクの紐付けを確認してエラーを返す ポイントは ○各自にabort(404)でもいいけど、重複を防ぎたいので、privateメソッドで、一つのメソッドにする。 TaskController.php public function showEditForm(Folder $folder, Task $task) { $this->checkRelation($folder, $task); // 以下略 } public function edit(Folder $folder, Task $task, EditTask $request) { $this->checkRelation($folder, $task); // 以下略 } private function checkRelation(Folder $folder, Task $task) { if ($folder->id !== $task->folder_id) { abort(404); } } エラー画面を作る // 403,404,500のファイルを作成する $ mkdir resources/views/errors $ touch resources/views/errors/403.blade.php $ touch resources/views/errors/404.blade.php $ touch resources/views/errors/500.blade.php resources/views/errors/403.blade.php @extends('layout') @section('content') <div class="container"> <div class="row"> <div class="col col-md-offset-3 col-md-6"> <div class="text-center"> <p>お探しのページにアクセスする権限がありません。</p> <a href="{{ route('home') }}" class="btn"> ホームへ戻る </a> </div> </div> </div> </div> @endsection resources/views/errors/404.blade.php @extends('layout') @section('content') <div class="container"> <div class="row"> <div class="col col-md-offset-3 col-md-6"> <div class="text-center"> <p>お探しのページは見つかりませんでした。</p> <a href="{{ route('home') }}" class="btn"> ホームへ戻る </a> </div> </div> </div> </div> @endsection resources/views/errors/500.blade.php @extends('layout') @section('content') <div class="container"> <div class="row"> <div class="col col-md-offset-3 col-md-6"> <div class="text-center"> <p>サーバー上のエラーが起きました。申し訳ありませんが、以下のリンクからホーム画面へお戻りください。</p> <a href="{{ route('home') }}" class="btn"> ホームへ戻る </a> </div> </div> </div> </div> @endsection 今回はここで終了します。 いよいよ次回大詰めです。 ここまででアプリの開発自体は終了です。 ということで、次回はデプロイをする感じです。 それでは、ここまでご覧頂きありがとうございました。 次回の記事をお楽しみに。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel ~テーブルとデータの作成~

はじめに Laravelの勉強を開始して、約3ヶ月経ったので備忘録として記事に残しておきます。 動作環境 PHP Laravel MySQL 7.1.19 5.6.27 5.7.22 データベース作成 MySQLで今回使用するデータベースを作成します。 mysql > create database データベース名; .envファイル編集 .env DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=データベース名 DB_USERNAME=MYSQLのユーザー名 DB_PASSWORD=設定しているパスワード これで作成したデータベースをLaravelで使用できる。 migrationファイル作成 artisanコマンドで下記を実行するとdatabase/migrations/にmigrationファイルが作成される。 php artisan make:migration create_books_table --create=books yyyy_mm_dd_xxxxxx_create_books_table.php <?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateBooksTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('books', function (Blueprint $table) { $table->increments('id'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('books'); } } このファイルにカラムを追加していく。 カラム作成例 記載方法 情報 $table->increments(カラム名); 主キー $table->integer(カラム名); INT型 $table->string(カラム名, 文字数); VARCHAR型 $table->text(カラム名); TEXT型 $table->dateTime(カラム名); 日付と時間 $table->timestamps(カラム名); created_at, update_at $table->softDeletes(カラム名); deleated_at 編集終わったら、マイグレーションを実行する。 そうするとbooksテーブルが作成される。 php artisan migrate 特定のmigrationファイルをマイグレーション実行する際は下記のコマンドを実行する。 php artisan migrate:refresh --step=1 --path=/database/migrations/yyyy_mm_dd_xxxxxx_create_books_table.php 作成したテーブルを削除する際はロールバックすれば良い。 php artisan migrate:rollback 初期データ作成 今回は、seederという機能を使用して初期データを作成していく。 ますは、seederファイルの作成から始めます。 php artisan make:seeder BooksTableSeeder 上記コマンド実行することによってdatabase/seeds/以下に、BooksTableSeeder.phpが作成される。 BooksTableSeeder.php <?php use Illuminate\Database\Seeder; class BooksTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { // } } 上記のrunメソッド内に追記していく。 例えば、、、 カラム名 => 初期データ で記述していく BooksTableSeeder.php public function run() { DB::table('books')->truncate(); //データのクリア DB::table('books')->insert([ //booksテーブルに登録するレコードを配列で記述していく [ 'name' => 'コロコロコミック', 'created_at' => Carbon::create(2018, 1, 1), 'updated_at' => Carbon::create(2018, 1, 4), ], [ 'name' => 'ゼクシィ', 'created_at' => Carbon::create(2018, 2, 1), 'updated_at' => Carbon::create(2018, 2, 5), ], ]); } 上記でCarbonという日付操作のライブラリを使用している。 使用のためには、use Carbon\Carbon;の記述必須。 記述終わったら、作成したseederファイルで初期データを投入するために同じディレクトリにある DatabaseSeeder.phpに以下のように追記する。 DatabaseSeeder.php <?php use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { $this->call(BooksTableSeeder::class); //この部分を追記 } } 最後に下記のコマンドを実行することで、初期データ作成完了!! php artisan db:seed 参考 https://readouble.com/laravel/5.5/ja/migrations.html https://readouble.com/laravel/5.5/ja/seeding.html
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む