- 投稿日:2021-01-22T23:57:30+09:00
PHPでログイン機能
前回の続きです。
PHPカレンダー:https://qiita.com/x49_n/items/64a04a85b72c6d581421ログイン機能作成
前回作成したカレンダーにログイン機能を追加していきます。
ご参考に:https://www.youtube.com/watch?v=uCvPMe5wsNk
ログイン機能
・新規登録(ユーザー登録)
・ログイン+ログイン確認画面
・ログアウト+ログアウト確認画面ER図
簡単ですが、ER図を作成しました。(本当はツールを使って作成したかった、、、)
ER図動画化したものについてはTwitterにて公開しています。
https://twitter.com/x49_n/status/1352600436616830976次回は予定入力欄を作成します!
- 投稿日:2021-01-22T23:29:47+09:00
Laravelで画像を表示する方法
PHP、Laravelの初学者です。
Laravelで画像を表示させる方法がわかったので、メモしておきたいと思います。
※ 使用しているLaravelのバージョンは6.xです。違うバージョンをご使用の方はご注意ください。
また、私はMacを使用しているので、Windowsをご使用の方もご注意ください。Laravelで画像を表示させる方法
①「自分のプロジェクト/storage/app/public」の中に利用したい画像を置く。
私は「/storage/app/public」にtop-page.jpgを入れました(以下の画像をご覧ください)。
② シンボリックリンクを張る
Laravel6.xの公式ドキュメントを見たところ、
「/storage/app/public」においた画像を使えるようにする(Webからのアクセスを許す)には、
「『public/storage』から『storage/app/public』へシンボリックリンクを張る」という作業が必要になるようです。シンボリックリンクって何だろう??
シンボリックリンクとは、オペレーティングシステム(OS)のファイルシステムの機能の一つで、特定のファイルやディレクトリを指し示す別のファイルを作成し、それを通じて本体を参照できるようにする仕組み。
んー。まだ難しい。
もう少し噛み砕いて説明された記事がありました。要は「代理人」のような役割を持つのが、このシンボリックリンクだそうです。
例を引用させていただくと例えば、ファイルAと、シンボリックリンクA’があるとしましょう。
シンボリックリンクA’は、ファイルAのシンボリックリンクです。このシンボリックリンクA’を開くと、ファイルAが開きます。
ファイルAを直接開いたのと同じ結果です。要は、代理人みたいなものですね。
シンボリックリンクは、自分がそのファイルやフォルダであるかのように振る舞います。とのことです。
さて、前置きが長くなりましたが、このシンボリックリンクを張るには、以下のコマンドを実行しましょう。
ターミナルphp artisan storage:link③シンボリックリンクを張ることができたら、ビューファイルに以下のように記述すれば画像を表示できます。
index.blade.php<img src="/storage/top-page.jpg">こんな感じで成功しました!
以上です。
何かありましたらコメントで教えていただけますと幸いです。ここまで読んでいただきありがとうございました。
- 投稿日:2021-01-22T22:15:55+09:00
JSとLaravelでAPI通信する際に日付データを合わせる(unixtime <-> Date)
概要
サーバーさん => Sさん
フロントさん => Fさんあるときこんなやりとりを目撃しました。
Sさん < 日付のフォーマットは20200222で送ってください
Fさん < ここは2020/02/22で送ってください
Sさん < この場合は2020-02-22で送ってください
続く....そのとき第三者の私はこう思いました。
私 < Unixtimeでやりとりすれば、同じフォーマットでやりとりできるんじゃね?と...
やってみた。
javascript// Date -> UnixTime new Date().getTime() / 1000; // 1611320223.828 // UnixTime -> Date new Date(unixTime * 1000); // Fri Jan 22 2021 21:57:44 GMT+0900 (日本標準時)※バックエンドはLaravelを使用しています
php// Date -> UnixTime $date = new DateTime('now'); $date->format('U'); // "1611320663" // UnixTime -> Date $dateTime = new DateTime('@' . (int)$unixTime); $dateTime->setTimeZone(new DateTimeZone('Asia/Tokyo')); // 2021-01-22 22:04:23.0 Asia/Tokyo (+09:00)感想
一旦これでUnixtimeでやりとりできそう!
もっと良いやり方などがありましたら教えてください。
- 投稿日:2021-01-22T21:01:03+09:00
フレームワークとは
今回はフレームワークについて学習をしました。フレームワークとは何か、Ruby,PHP,JavaScript,CSSの代表的なフレームワークを公式サイトとURLと共に紹介します。
説明不足があると思いますので、気になったフレームワークを公式サイトで確認してみて下さい。フレームワークとは
「フレームワーク」という言葉には、「枠組み」という意味があり、アプリケーション開発においては、テンプレートの役割を持っています。テンプレートの機能は、開発を行う際に頻繁に必要とされる「基礎的な機能」をまとめて提供してくれるものです。
例えば、ログイン認証機能、新規投稿機能、検索機能などアプリケーション開発においてほとんど共通して使われる機能がパッケージ化されています。
そのため、フレームワークを用いることで開発を高速化させることが出来ます。
どれくらい便利なものかというと、ログイン認証を仮に自分で1から作成したとします。その場合、作らなければならないのが、ユーザーネーム、パスワードの欄を作り、それを認証、弾く機能、更にそれらを管理する画面など様々なところを作っていかなければなりません。しかし、フレームワークを使うことで、これらのベースとして使える骨組み部分がパッケージ化されているので、あとは自分好みに改良するだけで済みます。このパッケージのことをフレームワークと呼びます。もっと簡単に言えばコンピュータ言語を使用して何か開発したいと考えたとき、その手助けをしてくれる便利ツールの1つと考えておけば良いでしょう。
私がよくお世話になっているものだとRubyならRuby on Rails、CSSならBootstrapなどがあります。おすすめなフレームワーク
フレームワークには言語ごとにたくさんの種類があります。しかし、ここでは私が実際におすすめされた・よく聞くフレームワークを紹介していきます。
Rubyのオススメフレームワーク3種
- Ruby on Rails 公式サイト <https://rubyonrails.org/>
- Sinatra 公式サイト <http://sinatrarb.com/intro-ja.html>
- Padrino 公式サイト <http://padrinorb.com/>Ruby on Rails
「Rubyのフレームワークは?」と聞けば、ほとんど返ってくる答えが「Ruby on Rails」と言われるほど有名です。正直に言ってしまえば、Rubyでアプリ、システム開発を行いたいなら、Ruby on Railsを選択すれば間違いないでしょう。私自身一番最初に手をるけたのがRuby on Railsでした。また、素早くかつ効率的に開発するために、2つの大原則を設定しているのが特徴です。
それらの原則について私が紹介した記事がありますので、読んでみてください。
「DRY原則・CoC原則とは」
https://qiita.com/Shirosan10/items/84fe66955398e91f7136
このように徹底的に規約に従って行動することで、Webアプリ開発の高速化を目指します。Sinatra
Rubyで記述されているオープンソースのフレームワークになります。フレームワークの中では、最も少ないコードでWebアプリなどの開発が可能です。
そのため学習コストが少なくて済み、最も手軽にフレームワークを使用した開発を始めることができます。Padrino
先述の、Sinatraをベースに設計されたフレームワークになります。Sinatraにはなかった機能群があり、かつRuby on Railsよりも少ないコードでWebアプリ開発ができるので、初心者だけど、少々複雑なものを開発したい人向けです。
PHPのオススメフレームワーク3種
- Laravel 公式サイト <https://laravel.com/>
- CakePHP 公式サイト <https://cakephp.org/jp>
- FuelPHP 公式サイト <http://fuelphp.jp/>Laravel
数あるPHPのフレームワークで、Laravelは2011年に登場した最も若いフレームワークです。今現在注目度が高く、その理由は「Love beautiful code? We do too」という理念どおり、初心者であっても美しいコードを書ける点だと思います。コードが書きやすく、すぐに書き始めることができるので、PHPを習得した人が真っ先に使用できます。
CakePHP
PHPの中でも有名なフレームワークです。「ケーキを焼くように簡単に開発」を理念として開発されており、Ruby onRailsの影響も強く受けています。
特徴的なのは、MVC(モデル・ビュー・コントローラ)モデルと呼ばれる実装デザインに関する先駆けになったことです。
MVCモデルについて気になった方はこちらも読んでみてください。
拙いながらMVCについて図解を入れて解説しています。
「MVCモデルについて」
https://qiita.com/Shirosan10/items/d12416700f7e2329cb09FuelPHP
FuelPHPもLaravelと同じように、比較的最近登場したフレームワークです。そのため、ほかのPHPフレームワークの良いところ吸収しているので、使いやすいフレームワークです。
特徴としては、動作が軽量でフレームワークの規約が少ないため、自由にコードを記述出来ることが挙げられます。JavaScriptのオススメフレームワーク3種
- AngularJS 公式サイト <https://angularjs.org/>
- Vue.js 公式サイト <https://jp.vuejs.org/index.html>
- React 公式サイト <https://ja.reactjs.org/tutorial/tutorial.html>AngularJS
AngularJSはJavaScriptでできたWebフレームワークです。見た目の動きをきれいに作るために使用されます。
例えば、SPA(Single-page application)と呼ばれる、「ページを移動しなくてもなめらかにページ内のコンテンツが現れるような1ページで完結するアプリケーション」の開発を行う時などに採用されます。Vue.js
Vue.jsはAngularJSよりも後に開発されいます。そのため、他のフレームワークの良いところを組み込んだ設計になっています。
AngularJSよりも規約が少ないため、比較的自由にコードを記述出来、JavaScriptを学習したばかりの初心者におすすめされます。React
有名なSNS「Facebook」が中心となって開発したフレームワークです。React Nativeと呼ばれる、全く同じソースコードでiOSとAndoroidアプリ両方を動作させることが可能なため、モバイルアプリ開発に適しています。
CSSのオススメフレームワーク
Bootstrap 公式サイト <https://getbootstrap.com/>
Bootstrapは「Webデザインフレームワーク」と呼ばれ、CSS/JavaScriptから構成されています。Twitter社より提供されるフレームワークになるため、Twitterのようなフラットなデザインを簡単に作成することができます。クラスを指定するだけで簡単にレスポンシブデザインに対応したページを作ることが出来ます。
今回の記事は以上になります。
色々と拙い部分があるかと思います。
また、自分が実際に使っておらず調べたり、教科書に書いて有りそうな説明なってしまったものもあり、説明が淡々としすぎてしまいました。今後、自分で使いたいなと思ってメモしていたので理解が深まったら更新して行こうと思います。
間違っている点、理解が不完全な点があればご指摘いただければ幸いです。
- 投稿日:2021-01-22T19:11:21+09:00
WP_Queryのクエリ参考
WordPress
WordPressのWP_Queryスニペットコードまとめ
wp_query.php<?php $args = array( // ↓ 特定の「著者」に関連付けられた投稿を表示する場合 'author' => '1,2,3', // 著者IDを指定 'author_name' => 'solecolor', // user_nicenameを指定(名前ではありません) 'author__in' => array( 2 , 6 ), // 著者IDを配列で指定(著者IDを含む記事を絞り込む) 'author__not_in' => array( 2 , 6 ), // 著者IDを配列で指定(著者IDを含まない記事を絞り込む) // ↓ 特定の「カテゴリー」に関連付けられた投稿を表示する場合 'cat' => 5, // カテゴリーIDを指定 'category_name' => 'daily, news', // カテゴリースラッグを指定(複数の場合は「,」で区切る) 'category__and' => array( 2 , 6 ), // カテゴリーIDを配列で指定(カテゴリーIDを含む記事を絞り込む) 'category__in' => array( 2 , 6 ), // カテゴリーIDを配列で指定(カテゴリーIDを含む記事を絞り込む) 'category__not_in' => array( 2 , 6 ), // カテゴリーIDを配列で指定(カテゴリーIDを含まない記事を絞り込む) // ↓ 特定の「タグ」に関連付けられた投稿を表示する場合 'tag' => 'cooking', // タグスラッグを指定 'tag_id' => 5, // タグIDを指定 'tag__and' => array( 2 , 6 ), // タグIDを配列で指定(タグIDを含む記事を絞り込む) 'tag__in' => array( 2 , 6 ), // タグIDを配列で指定(タグIDを含む記事を絞り込む) 'tag__not_in' => array( 2 , 6 ), // タグIDを配列で指定(タグIDを含まない記事を絞り込む) 'tag_slug__and' => array( 'red', 'blue' ), // タグスラッグを配列で指定(タグスラッグを含む記事を絞り込む) 'tag_slug__in' => array( 'red', 'blue' ), // タグスラッグを配列で指定(タグスラッグを含む記事を絞り込む) // ↓ 特定の「タクソノミー」に関連付けられた投稿を表示する場合(以下は複数のタクソノミーにてAND検索) 'tax_query' => array( // タクソノミーパラメーターを指定 'relation' => 'AND', // タクソノミーの検索条件に 'AND' か 'OR' が使用可能 array( 'taxonomy' => 'color', // タクソノミーを指定 'field' => 'slug', // term_id(デフォルト),name,slug のいずれかのタームの種類を選択 'terms' => array( 'red', 'blue' ), // ターム(文字列かIDを指定) 'include_children' => true, // 階層を持つタクソノミーの場合に、子孫タクソノミーを含めるかどうか 'operator' => 'IN' // 演算子'IN','NOT IN','AND','EXISTS'(4.1.0以降),'NOT EXISTS'(4.1.0以降)が利用可能 ), array( 'taxonomy' => 'actor', 'field' => 'id', 'terms' => array( 103, 115, 206 ), 'include_children' => false, 'operator' => 'NOT IN' ) ), // ↓ 特定の「投稿&固定ページ」に関連付けられた投稿を表示する場合 'p' => 1, // 投稿IDを指定 'name' => 'hello-world', // 投稿スラッグを指定 'page_id' => 1, // 固定ページのIDを指定 'pagename' => 'sample-page', // ページスラッグを指定 'pagename' => 'contact_us/canada', // 子ページを表示する場合、スラッシュ区切りで親と子のスラッグを指定 'post_parent' => 1, // ページIDを指定した子ページを表示 'post_parent__in' => array( 1, 2, 3 ), // 配列の親ページIDを含む投稿を表示 'post_parent__not_in' => array( 1, 2, 3 ), // 配列の親ページIDを含まない投稿を表示 'post__in' => array( 1, 2, 3 ), // 配列の投稿IDを含む投稿を表示 'post__not_in' => array( 1, 2, 3 ), // 配列の投稿IDを含まない投稿を表示 // ↓ 特定の「パスワード」に関連付けられた投稿を表示する場合 'has_password' => true, // パスワード付きの投稿を表示( true or false ) 'post_password' => 'zxcvbn', // 特定のパスワードが付いた投稿を表示 // ↓ 特定の「タイプ」に関連付けられた投稿を表示する場合 'post_type' => array( 'post', // 投稿 'page', // 固定ページ 'revision', // リビジョン 'attachment', // 添付ファイル 'custom-post-type' // カスタム投稿タイプ ), 'post_type' => 'any', // すべてのタイプを含めて表示(リビジョンと'exclude_from_search'がtrueにセットされたものを除く) // ↓ 特定の「投稿ステータス」に関連付けられた投稿を表示する場合 'post_status' => array( // 投稿ステータスを指定 (デフォルト'publish') 'publish', // 公開された投稿、または固定ページを表示 'pending', // レビュー待ちの投稿を表示 'draft', // 下書きの投稿を表示 'auto-draft' // コンテンツのない、新しく作成された投稿を表示 'future', // 予約公開設定された投稿を表示 'private', // ログインしていないユーザーには見えない投稿を表示 'inherit', // リビジョンを表示 'trash', // ゴミ箱に入った投稿を表示 ), 'post_status' => 'any', // すべてのステータスを表示(投稿タイプで'exclude_from_search'がtrueにセットされたものを除く) // ↓ ページ送りパラメーターを設定する場合 'posts_per_page' => 10, // 1ページあたりに表示する投稿数を指定(-1を指定するとすべての投稿を表示) 'posts_per_archive_page' => 10, // 1ページあたりに表示する投稿数(アーカイブページのみ) 'nopaging' => false, // ページ送りを使用するか、すべての投稿を表示するか、(デフォルトはfalseでページ送りを使用) 'paged' => 6, // ページ番号6の記事を表示 'paged' => get_query_var('paged'), // 現在のページから投稿を表示 'offset' => 3, // 設定した数だけ、ずらして表示(例では4番目の投稿から表示) 'ignore_sticky_posts' => false, // 先頭固定表示投稿を無視するかどうか(デフォルト値は0で先頭固定表示投稿を無視しない) // ↓ 「投稿の並び順」を指定する場合 'order' => 'DESC', // 'ASC' 昇順 (1, 2, 3; a, b, c) // 'DESC' 降順 (3, 2, 1; c, b, a) 'orderby' => 'date', // デフォルト値'date' 複数のオプションを渡すことが可能 // 例:'orderby' => 'menu_order title' // その他のオプション ↓ //'none' 並び替えなし //'ID' 投稿IDで並び替え //'author' 著者で並び替え //'title' タイトルで並び替え //'name' Order by post name(post slug) //'modified' 更新日で並び替え //'parent' 親ページIDで並び替え //'rand' ランダム順 //'comment_count' コメント数で並び替え //'menu_order' ページの表示順で並び替え //'meta_value' アルファベット順で並び替え(数値ではうまくいかない) //'meta_value_num' 数値で並び替え //'post__in' post__inで配列で指定された投稿IDの並び順を維持して表示 // ↓ 特定の「時間や日付の期間」に関連付けられた投稿を表示する場合 'year' => 2015, // 4桁の年を数字で指定(2015など) 'monthnum' => 4, // 月を数字で指定( 1~12 ) 'w' => 25, // 年内の週を数字で指定( 0~53 ) 'day' => 17, // 月内の日を数字で指定( 1~31 ) 'hour' => 13, // 時間を数字で指定( 0~23 ) 'minute' => 19, // 分を数字で指定( 0~60 ) 'second' => 30, // 秒を数字で指定( 0~60 ) 'm' => 201404, // 年と月を数字で指定 ( 201508など ) // ↓ 「○年○月○日から○年○月○日の範囲の投稿情報」を表示する場合(投稿日の検索が自由自在!) 'date_query' => array( array( 'year' => 2015, // 4桁の年を数字で指定(2015など) 'month' => 8 // 月を数字で指定( 1~12 ) 'week' => 31 // 年内の週を数字で指定( 0~53 ) 'day' => 5 // 月内の日を数字で指定( 1~31 ) 'hour' => 2 // 時間を数字で指定( 0~23 ) 'minute' => 3 // 分を数字で指定( 0~60 ) 'second' => 36 // 秒を数字で指定( 0~60 ) 'after' => 'January 1st, 2013', // 指定した日付以降の投稿を取得。strtotime()と互換性のある文字列で'after'=>'2015/08/31'などでもOK 'before' => array( // 指定した日付以前の投稿を取得。strtotime()と互換性のある文字列で'before'=>'2015/08/31'などでもOK 'year' => 2013, // 4桁の年を数字で指定(2015など) デフォルトは空 'month' => 2, // 年内の月を数字で指定( 1~12 ) デフォルトは12 'day' => 28, // 月内の日を数字で指定( 1~31 ) デフォルトは月内の末日 ), 'inclusive' => true, //「after」または「before」パラメーターで指定された値を含むかどうか 'compare' => '=', // 使用可能な値は '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN', 'EXISTS' , and 'NOT EXISTS' 'column' => 'post_date', // 照会するカラムを指定。デフォルトは「post_date」 'relation' => 'AND', // OR または AND デフォルトは「AND」 ), ), // ↓ 特定の「カスタムフィールド」に関連付けられた投稿を表示する場合 'meta_key' => 'key', // カスタムフィールドのキーを指定 'meta_value' => 'value', // カスタムフィールドの値を指定 'meta_value_num' => 10, // カスタムフィールドの値を指定 'meta_compare' => '=', //「meta_value」をテストする演算子。使える値は'!='、'>'、'>='、'<'、'=' デフォルト値は'=' 'meta_query' => array( // カスタムフィールドパラメーター 'relation' => 'AND', // 「AND」または「OR」を指定。meta_query内の配列が「2つ以上」の場合に限る。meta_query配列が1つの場合は使用しない。 array( 'key' => 'color', // カスタムフィールドのキー。 'value' => 'blue', // カスタムフィールドの値 (注意 compareの値が'IN'、'NOT IN'、'BETWEEN'、'NOT BETWEEN'のみ配列をサポート) 'type' => 'CHAR', // カスタムフィールドタイプ。タイプについては以下の「meta_queryで使えるデータ型」参照 'compare' => '=', // 演算子を指定 デフォルト値は'=' 演算子の種類については以下「meta_queryで指定できる演算子の種類」参照 ), array( 'key' => 'price', 'value' => array( 1,200 ), 'compare' => 'NOT LIKE', ) ), // ↓ 適切な権限を持っているユーザーのプライベートの記事を表示する場合 'perm' => 'readable' // 使える値は’readable’と’editable’ // ↓ キャッシュ系のパラメーター 'cache_results' => true, // 投稿情報をキャッシュするかどうか デフォルトはtrue 'update_post_term_cache' => true, // 投稿タームキャッシュを更新するかどうか デフォルトはtrue 'update_post_meta_cache' => true, // 投稿メタキャッシュを更新するかどうか デフォルトはtrue 'no_found_rows' => false, // カウントをスキップする? tureでパフォーマンスが向上する可能性があるかも デフォルトはfalse // ↓ 検索系のパラメーター 's' => $s, // 検索からクエリーストリング値を渡します。 'exact' => true, //タイトル/投稿の全体から正確なキーワードで検索するか デフォルト値はfalse 'sentence' => true, //語句(フレーズ検索)で検索するか デフォルト値はfalse // ↓ 投稿フィールドパラメーター 'fields' => 'ids' //1つのフィールドで返すか全てのフィールドで返すか デフォルトでは全てのフィールドが返される // 使用できる値↓ // 'ids' 投稿のIDの配列を返します // 'id=>parent' 連想配列を返します ); $query = new WP_Query( $args ); if ( $the_query->have_posts() ) : while ( $the_query->have_posts() ) : $the_query->the_post(); // 何かしらの処理 endwhile; endif; // 投稿データのリセット wp_reset_query(); ?>簡単な説明
データ 内容 CHAR 文字 NUMERIC ‘SIGNED’の別名 DECIMAL 浮動小数点数 SIGNED 整数(符号あり) UNSIGNED 整数(符号なし) DATE 日付 DATETIME 日時 TIME 時刻 BINARY バイナリー
比較演算子 内容 = 値と一致する != 値と一致しない > 値より大きい >= 値以上 < 値より小さい <= 値以下 LIKE 値で指定した文字列に一致する場合 NOT LIKE 値で指定した文字列に一致しない場合 IN 値(配列)で指定した何れかに一致する場合 NOT IN 値(配列)で指定した何れかにも一致しない場合 BETWEEN 2つの値で指定した範囲内(境界を含む)場合 NOT BETWEEN 2つの値で指定した範囲外の場合 タクソノミーで設定したACFの取得
wp_query.php$taxonomy_name = 'com_category'; $taxonomys = get_the_terms( $post->ID, $taxonomy_name); if(!is_wp_error($taxonomys) && count($taxonomys)){ foreach($taxonomys as $taxonomy){ // print_r($taxonomy); $staff_title = $taxonomy->name; $staff_description = $taxonomy->description; $staff_img = get_field('staff_img', $taxonomy_name . "_" . $taxonomy->term_id); echo '<p>' . $staff_title . '</p>'; echo '<p>' . $staff_description . '</p>'; echo '<p><img src="' . $staff_img . '"></p>'; } }参考記事
http://notnil-creative.com/blog/archives/1288
https://elearn.jp/wpman/column/c20110906_01.html
https://hirashimatakumi.com/blog/164.html
- 投稿日:2021-01-22T18:12:39+09:00
PHPのバージョンを8.0にアップデートする
課題
PHPのバージョンをアップデートする
現状のバージョンを確認する
下記のコマンドでバージョンを確認
ターミナル$ php -v PHP 7.4.7 (cli)*ちなみにですが今回はHomebrewを使ってアップデートしようと思います
Homebrewのインストールがまだという方はこちらをソッと置いておきます
(https://brew.sh/index_ja.html)PHP8系を検索する
次にHomebrewコマンドを使って現在インストールができるPHPのバージョンを検索します
ターミナル$ brew search php@8 ==> Formulae php@8.0最新のPHP 8.0 をインストールしてみる
どのバージョンをインストールするか決めたら
PHP 8.0を Homebrew経由でインストールしますターミナル$ brew install php@8.0PATHを通そう
インストールは無事にされたと思いますが、まだ終わりではありません
PATHを通す必要があるので下記コマンドにて設定を上書きしますターミナル$ echo 'export PATH="/usr/local/opt/php@8.0/bin:$PATH"' >> ~/.bash_profile $ echo 'export PATH="/usr/local/opt/php@8.0/sbin:$PATH"' >> ~/.bash_profilePHPとの冒険の再出発へ
上書きまで できたら下記コマンドでPHPを再スタートさせます
ターミナル$ brew services start php@8.0ここで一旦ターミナルを閉じます。
大事なことなのでもう一度言います。ここで一旦ターミナルを閉じます。
ターミナルをもう一度起動させたらバージョンを確認してみます
ターミナル$ php -v PHP 8.0.1 (cli)これで完了です!
- 投稿日:2021-01-22T18:03:26+09:00
PHP入門 文法編
0.what
php文法を自分なりに整理していきます.
1.画面表示
1.1."Hello World"
index.php<?php //基本は print(); の形 print("Hello World"); //Hello World1.2.数字、文字、日本語表示
index.php//number print(123); //改行 print('<br>'); print("日本語"); //123 //日本語2.演算
2.1.基本演算
index.php//"."で連結. print(7 + 3."<br>"); //10 print(7 - 3."<br>"); //4 print(7 * 3."<br>"); //21 print(7 / 3."<br>"); //2.3333333333333 print(7 % 3."<br>"); //12.2.変数
index.php//$後の先頭は英文字か_ $test = 123; print($test); var_dump($test); //123int(123) $num1 = 123; $num2 = 456; $num3 = $num1.$num2; print($num3.'<br>'); var_dump($num3); //string(6) "123456"2.3.定数
index.phpconst NUMBER = 7; const NUMBER = 0; print(NUMBER.'<br>'); //73.配列
3.1.初期化
index.php//初期化 $array = [1,2,3,'A']; print($array.'<br>'); //Array print($array[1].'<br>'); //2 var_dump($array); //array(4) { [0]=> int(1) [1]=> int(2) [2]=> int(3) [3]=> string(1) "A" }3.2.多次元配列
index.php$array_2 = [[1,2,3], [4,5,6], [7,8,9]]; print($array_2[1][1]."<br>"); //5 var_dump($array_2); //array(3) { [0]=> array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) } [1]=> array(3) { [0]=> int(4) [1]=> int(5) [2]=> int(6) } [2]=> array(3) { [0]=> int(7) [1]=> int(8) [2]=> int(9) } }3.3.連想配列
keyとvalueを持つ辞書型の配列.
index.php$array_member = [ 1 => 'one', 2 => 'two', 3 => 'three' ]; print($array_member[1]."<br>"); //one var_dump($array_member); //array(3) { [1]=> string(3) "one" [2]=> string(3) "two" [3]=> string(5) "three" }3.4.配列がvalue
index.php$array_member_2 = [ 'A' => [ 'id' => 0, 'height' => 180, 'weight' => 56 ], 'B' => [ 'id' => 1, 'height' => 140, 'weight' => 55 ] ]; print($array_member_2['A']['height']."<br>"); //1804.条件分岐
4.1.if else
index.php$num = 0; if ($num > 0){ print($num." is +"."<br>"); } else if ($num == 0){ print($num." is 0 "."<br>"); } else{ print($num." is -"."<br>"); } //0 is 0 var_dump($argv); $num = $argv[1]; if ($num%2 == 0){ echo('偶数'.PHP_EOL); } else{ echo('奇数'.PHP_EOL); }4.2.型まで比較
index.phpone_n = 1; $one_s = '1'; if ($one_n === $one_s){ print("型は同じ<br>"); }else{ print("型が違う<br>"); } //型が違う4.3.空データか確認
index.php$str=null; if (empty($str)){ print("空データ<br>"); } //空データ他にも
isset
,is_null
などで調べる.4.4.三項演算子
index.php$max = 80; $comment = $max == 100 ? 'True' : 'False'; print($comment."<br>");4.5.swhich
index.php$data=4; switch($data){ case 1: print("1"); break; case 2: print("2"); case 3: print("3"); case 4: print("4"); break; default: print("no"); } //45.繰り返し処理
5.1.foreach文
index.php$numbers = [ "one", "two", "three", "four", "five" ]; foreach($numbers as $number){ print($number."<br>"); } //one //two //three //four //five5.2.連想配列取得
index.php$numbers_2 = [ 1=>"one", 2=>"two", 3=> "three" ]; foreach($numbers_2 as $key => $value){ print("key=".$key."value=".$value."<br>"); } //key=1value=one //key=2value=two //key=3value=three5.3.for文
index.phpfor ($i=1; $i<=100; $i++){ if ($i % 15 == 0){ echo('FizzBuzz'.PHP_EOL); } elseif($i % 3 == 0){ echo('Fizz'.PHP_EOL); } elseif($i % 5 == 0){ echo('Buzz'.PHP_EOL); } else{ echo($i.PHP_EOL); } }5.4.while文
index.php$j = 10; while($j > 0){ print($j." "); $j--; } //10 9 8 7 6 5 4 3 2 15.5.do while文
index.phpdo{print($j); $j++;} while($j < 5); //012346.関数
6.1.関数の基本
index.phpfunction sumP($int1, $int2){ return $int1+$int2; } $sum_number = sumP(4,7); //116.2.文字列関数
index.php$str1 = "abc"; $str2 = "日本語"; //文字列の長さ(日本語は3bit) print(strlen($str1)."<br>"); //3 print(strlen($str2)."<br>"); //9 //基本はmb_strlen()を使用 print(mb_strlen($str2)."<br>"); //3 //文字列の置換 print(str_replace('b','B',$str1)); //aBc //文字列で分割 $pro = "34 44 33 22"; foreach(explode(" ", $pro) as $pr){ print($pr." "); } // 34 44 33 22 //特定の文字が含まれるか $str3 = "eggs@gg"; print(preg_match('/@/',$str3)."<br>"); //1 //文字列取得 スライス的な役割 print(mb_substr($str3, 2)."<br>"); //gs@gg6.3.配列関数
index.php$foods = ["pizza", "ramen", "yakiniku"]; //追加 array_push($foods, "potato");7'オブジェクト指向
7.クラス
7.1.クラスとインスタンス
instance.php<?php class Product{ //アクセス修飾子 private $product = []; //クラス呼び出し時 function __construct($product){ //$thisはこのクラスの意味 //このクラスのproductは引数のproduct $this->porduct = $product; } public function getProduct(){ print($this->porduct); } public function addProduct($item){ //.=で追加 $this->porduct .= $item; } public static function getStaticProduct($str){ echo $str; } } //インスタンス化 $instance = new Product('test'); $instance->getProduct(); //test print('<br>'); $instance->addProduct('add'); $instance->getProduct(); //testadd print('<br>'); Product::getStaticProduct('string'); print('<br>'); //string7.2.継承
extends.php<?php //親クラス class Animal{ public $cry = "bowbow!"; public function bow(){ print($this->cry."<br>"); } } //子クラス class Dog extends Animal{ public $cry = "DOG!"; } $dog = new Dog(); $dog->bow(); //DOG!子クラスにfinalをつけると継承はそれ以降できなくなる.
7.3.抽象クラス
extends.php//抽象クラス abstract class ProductAbstract{ public function echoProduct(){ print("super class"); } //抽象クラスは中身をかけない abstract public function get(); } class prodct extends ProductAbstract{ //必ず抽象関数を入れる function get(){ print("Hello!"); } }7.4.インターフェース
interface.php<?php //インターフェースは抽象関数しか入れることができない interface ProductInterface{ public function getProduct(); } interface NewInterface{ public function Product(); } //継承はいくつでも可能 class Products implements ProductInterface, NewInterface{ function getProduct(){ print("Hello "); } function Product(){ print("3,2,1<br>"); } }7.5.トレイト
trait.php<?php trait ProductTrait{ public function getProduct(){ print("purduct"); } } trait NewsTrait{ public function getNews(){ print("News"); } } class Product{ use ProductTrait; use NewsTrait; public function getInformation(){ print("Hello"); } } $instance = new Product(); $instance->getInformation(); $instance->getProduct(); $instance->getNews();
- 投稿日:2021-01-22T17:54:57+09:00
Instagram HTML 埋め込み
よく仕様が変わって表示されなくなるそうですが、まだ僕はペーペーなので体験してません。
実装
コード
<?php $count = '6'; //画像取得数。ここは好きな表示枚数に変更 $id = '*****'; //InstagramビジネスアカウントID。取得方法は後述 $token = '*****'; // アクセス。取得方法は後述 $json = file_get_contents("https://graph.facebook.com/v9.0/{$id}?fields=name%2Cmedia.limit({$count})%7Bcaption%2Cmedia_url%2Cthumbnail_url%2Cpermalink%7D&access_token={$token}"); $json = mb_convert_encoding($json, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); $obj = json_decode($json, t $insta foreach ((array)$obj['media']['data'] as $k => $v) { if ($v['thumbnail_url']) { $data = [ 'img' => $v['thumbnail_url'], // 動画ならサムネ 'caption' => $v['caption'], // キャプション 'link' => $v['permalink'], // パーマリンク ]; } else { $data = [ 'img' => $v['media_url'], 'caption' => $v['caption'], 'link' => $v['permalink'], ]; } $insta[] = $data; foreach ($insta as $k => $v){ echo '<li><a href="'.$v['link'].'" target="_blank"><img src="'.$v['img'].'" alt="'.$v['caption'].'"></a></li>'; }; ?>Instagram グラフAPIの取得方法
- 表示させるインスタアカウントをプロアカウントに
- 当該インスタアカウントの管理者として、Facebookページ作成→当該Instagramアカウント紐付け
- Instagram グラフAPI からInstagramアカウントのAPI取得
- 1時間有効API取得
- 上記1.を使用して、2ヶ月有効API取得
- 上記2.を使用して、ずっと有効API取得
- ずっと有効API取得と、ずっと有効API取得を取得する途中で手に入るtokenを、上記コードの
$id
$token
に突っ込むちなみに
僕が実装するときもあまりふんだんに情報があるわけではなかったです。
どうせまた変わるかもしれないですし、とりあえず方法のみ。
詳細は実際にやりながらアウトラインつかむ感じでいい気がしました。
どうせまた変わるかもしれないですし。
とりあえず
PHPで埋め込んで
InstagramグラフAPIを3つ取得して最後のやつ使う
あたりを頭の端っこの方に入れとくといいかもです。どうせまた変わるかもしれないですし。
- 投稿日:2021-01-22T15:55:57+09:00
Laravel checkboxで複数取得する方法
はじめに
inputのcheckboxを使って
1. 複数チェックの取得
2. チェックしたデータを保持する方法
をまとめてみました。
テーブル設計とリレーション
今回は
usersテーブル
とcategoriesテーブル
使っていきます。userは複数のcategoryを持ち、categoryも複数のuserに紐づけられているので
多対多のリレーションになります。
テーブル設計
◎usersテーブル
migrationpublic function up() { Schema::create('users', function (Blueprint $table) { $table->increments('id'); $table->string('name'); }); }
◎categoriesテーブル
migrationpublic function up() { Schema::create('categories', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->timestamps(); }); }
◎category_userテーブル
migrationpublic function up() { Schema::create('category_user', function (Blueprint $table) { $table->increments('id'); $table->integer('user_id')->unsigned(); $table->integer('category_id')->unsigned(); $table->foreign('user_id')->references('id')->on('users')->OnDelete('cascade'); $table->foreign('category_id')->references('id')->on('categories')->OnDelete('cascade'); $table->timestamps(); }); }
category_userテーブルでmigration$table->foreign('user_id')->references('id')->on('users')->OnDelete('cascade'); $table->foreign('category_id')->references('id')->on('categories')->OnDelete('cascade');でOnDelete('cascade')をつけておきましょう。 後々でdetachのときに一緒に削除するためです
リレーション設計
User.phppublic function categories() { return $this->belongsToMany(Category::class); }ここまで出来たら次はコントローラーの作成に入ります
コントローラー設計
Contorllerpublic function update(Request $request) { $user = Auth::user(); $user->categories()->detach(); $user->categories()->attach($request->category);
$user->categories()
でリレーションをして、attach($request->category)
でリクエストするカテゴリーを紐付けます。テーブルで
OnDelete('cascade')
をつけたのは、detachで削除するときに、user_id
,category_id
を削除するためです。次はBladeの設計です
Bladeの設計
ここが結構悩みました。 データの取得は出来たのですが、編集するときにデータの保持するのがなかなか詰まりました。
最初はoldを使ってデータ保持をやろうとしたのですがなかなかうまく行かず、oldを使わないでchecked
が含まれてるときでif文を作りました。
blade@foreach ($categories as $category) @if($user->categories->contains('id', $category->id)) <input type="checkbox" name="category[]" value="{{ $category->id}}" checked> @else <input type="checkbox" name="category[]" value="{{ $category->id}}"> @endif <label for=""> {{ $category->name }} </label> @endforeach指定したidを判定するためにコレクションの
contains()
メソッドを使って、指定したidが含まれているか確認しました。ただ、oldを使ってデータ保持もやりたかったので、三項演算子を使って下記のようにも書いてみました。
blade@foreach($categories as $category) <input type="checkbox" name="category[]" id="" value="{{ $category->id }}" {{ $category->id == old('category', $user->categories->contains('id', $category->id) ?? '') ? 'checked' : ''}} > <label for="category"> {{ $category->name }} </label> @endforeach保存して、また編集画面に遷移してもチェックボックスにcheckがついています!
色々なやり方がありますがご参考までに!!参考
- 投稿日:2021-01-22T15:37:27+09:00
【PHP初心者】Laravelを2週間触ってみて理解したこと②【ルーティング】
1.はじめに
こんにちは。nakaです。
昨晩ホームベーカリーをセットし、今朝は小麦のいい匂いで朝を迎えました( ˘ω˘ )
パンが大好きなのでとても癒されました・・・さて本題に入ります!前回に引き続きLaravelについてまとめたいと思います。
前回の記事:【PHP初心者】Laravelを2週間触ってみて理解したこと今回はルーティングについてです。
2.ルーティングとは
初めてLaravelのソースを見たとき、「えーとControllerやろー・・・・ん?」
controllerにリクエストのURLがなくてびっくりしました。
Laravelは代わりにルーティングと呼ばれるものがその役割を担っているようです。
ルーティングのルートが「経路」と訳されるように、ユーザからのリクエストを受け取り、ある処理を実行するまでの案内人のようなイメージですね。ルーティングは「routes/web.php」で設定できます。
Larabelをインストール後は、デフォルトのページの設定がされています。web.php<?php /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */ Route::get('/', function () { return view('welcome'); });3.ルート定義メソッド
それでは上記ファイル(web.php)に書くHTTPリクエストに定義できるメソッドを見てみましょう。
メソッドでよく見るものは「GET」「POST」ですかね。// GETリクエスト Route::get($uri, $callback); // POSTリクエスト Route::post($uri, $callback); // putリクエスト Route::put($uri, $callback); // patchリクエスト Route::patch($uri, $callback); // deleteリクエスト Route::delete($uri, $callback);ちなみにルーティングにはルートファザードを使います。
ファザードとはクラスをインスタン化せずに実行できる機能のことです。4.コントローラーのルーティング
基本の形
例えばコントローラーへルーティングする際は、以下のように書きます。
web.phpRoute::get('sample', 'SampleController@index');
http://xxx/sample
へアクセスすると、SampleControllerのindex()が呼ばれます。パラメータ付き
またURLからパラメーターを取得したい場合は、以下のように書きます。
web.phpRoute::get('sample/edit/{id}', 'SampleController@edit');SampleContoroller.php<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class SampleController extends Controller { public function edit($id) { print_r($id); } }
http://xxx/sample/edit/1
へアクセスすると、「1」というパラメータを取得し、SampleContoroller.phpのedit()の$idという変数で値を取得できます。ルーティングに名前を付ける
またルーティングに名前をつけることもできます。
URLをわざわざ書かなくも名前で呼び出せます。web.phpRoute::get('sample', 'SampleController@index')->name('sample.index');6.リダイレクトのルーティング
上記の名前をつけると便利
web.phpRoute::get('sample', 'SampleController@index')->name('sample.index');SampleContoroller.phpreturn redirect()->route('sample.index');5.ルートのグループ化
ルーティングをグループ化できます。
URLをまとめるときに使う「prefix」
管理者と会員など権限が複数の時に使うと便利
// ごちゃごちゃ Route::get('admin/top', 'AdminContoroller@top'); Route::get('admin/setting', 'AdminContoroller@setting');// 見やすい Route::prefix('admin')->group(function () { Route::get('top','AdminContoroller@top'); Route::get('setting','AdminContoroller@setting'); });名前空間をまとめる「namespace」
配置先をまとめることができます。
以下の場合は、"App\Http\Controllers\Admin"のディレクトリ内を示しています。App\Http\Controllers\Admin\TopColler@top App\Http\Controllers\Admin\SettingContoroller@setting// ごちゃごちゃ Route::get('top','Admin\TopColler@top'); Route::get('setting','Admin\SettingContoroller@setting');// 見やすい Route::namespace('Admin')->group(function () { Route::get('top','TopColler@top'); Route::get('setting','SettingContoroller@setting'); });他ミドルウェアをまとめる「middleware」、ドメインをまとめる「domain」、ルート名をまとめることもできます。複数を一気に設定もできます(今回は割愛)
6.さいごに
忘れていましたがルーティングは
php artisan route:list
で一覧が確認できます。ルーティングを理解するとソースの流れがわかりますね。
次回はBladeについて書く予定です(゜レ゜)
マークダウン少しづつ慣れてきた。参考記事
Laravelルーティングの基本とよく使われるルーティングパターン
routesを使いこなす(3)prefixでgroupを分割
- 投稿日:2021-01-22T15:09:56+09:00
Amazon AWS Cloud9 開発環境を速攻で作る方法(令和最新版)
はじめに
以前、記事を書いた時は、公式ドキュメントに従うことで開発環境が速攻で作れました
ですが、デフォルトのプラットフォームが
Amazon LinuxからAmazon Linux 2 に変更になったからなのか、
公式ドキュメント通りにしても開発環境が作れなくなっていました。今回、開発環境をまた用意する必要があったので、改めて書くことにしました。
2021年1月時点でのやり方なので、
将来的には同じように実行しても、
開発環境が作れなくなっている可能性はあります。予めご了承ください。
要件
- Apache 2.4以上
- PHP 7.4以上
- MySQL(MariaDB) 10.2.10-MariaDB
PHPはデフォルトで7.2がインストールされていました。
ですが、今回用意しなければいけない環境はPHP7.4です。
yumにある最新のPHPは7.2までなので、
7.4を入れるためには、epelでリポジトリを追加する必要があります。また、MySQLもデフォルトでmariadbがインストールされてました。
これにより、今まで
sudo service mysqld restart
とか書いてた部分は
sudo service mariadb restart
という風に読み換える必要があります。インスタンスを作成
https://ap-northeast-1.console.aws.amazon.com/cloud9/home?region=ap-northeast-1
- 上記のサイトにアクセス
- 画面右上のリージョン表記が「東京」であることを確認。違う場合は「東京」に変更
- 「Create environment」ボタンをクリック
- Step 1 Name environment
- 開発環境の名前と説明。
- 各項目の入力内容を次のとおり設定する
- 「Name」に開発予定のプロジェクト名を入力する ※必須
- なんでもいいが、英数字のみで入力するのが無難
- 「Description」にプロジェクトの説明を入力する ※任意
- 日本語を入力しても良し
- Step 2 Configure settings
- 開発環境の基本的な設定。
- 各項目の入力内容を次のとおり設定する
- Environment type - Create a new instance for environment (EC2)
- Instance type - t2.micro (1 GiB RAM + 1 vCPU)
- Platform - Amazon Linux 2 (recommended)
- Cost-saving setting - After 30 minutes (default)
- IAM role - AWSServiceRoleForAWESCloud9 ※変更できない
- Network settings (advanced) - 何も変更しない
- Add new tag - 何も設定しない
- ここまで出来たら「Next step」ボタンをクリック
- Step 3 Review
- 設定内容の確認。
- 「Create environment」ボタンをクリック
- 開発環境の構築が完了するまで待つ
- ネットワーク速度にもよるが、だいたい5分以内に完了する
- ターミナル画面(
bash - "ip-***-**-**-***"
みたいなのが書いてあるタブ)が操作できるようになったらOK【初回のみ】環境構築
外観のカスタマイズ
デフォルトだと文字サイズが12pxで、老眼にはつらいので、もうちょっち上げます
- 画面左上 ツールバー Cloud9アイコン -> Preferences (Ctrl-,) をクリック
- サイドバーから User Settings -> Terminal をクリック
- Font Size を 14 にする
- Antialiased Fonts を チェック
- Blinking Cursor を チェック
- サイドバーから User Settings -> Code Editor (Ace) をクリック
- Font Size を 14 にする
- Antialiased Fonts を チェック
あとデフォルト背景が白のため、ドライアイにもきついので、黒系の外観にします
- 画面左上 ツールバー View -> Themes -> UI Themes -> Jett Dark をクリック
- 画面左上 ツールバー View -> Themes -> Monokai をクリック
- お好みで。私は Sublime Text 3 をよく使ってたので
【重要】隠しファイルを表示する設定にします。「
.htaccess
」などを表示するためです
- 画面左上 プロジェクト名の右の歯車アイコンをクリック
- Show Hidden Files をクリック
あとはPreferencesの設定項目をじっくり眺めてお好みでカスタマイズしてください
yum のアップデート
公式ドキュメントと同じく、とりあえずyumを更新します
ターミナル画面(
bash - "ip-***-**-**-***"
みたいなのが書いてあるタブ)で、
以下のコマンドをコピペしてEnterキーを押して実行しますsudo yum -y update2021.01.22 時点では、特に何も更新されませんでした
Apache が入っているかを確認
httpd -V
Apache/2.4.46 が最初からインストールされてました。
このままでいいので作業なし。PHP が入っているかを確認
php -v
PHP 7.2.24 (cli) (built: Oct 31 2019 18:27:08) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies入ってますが、7.2なので、要件より古いですね。
そこで、PHP7.4にアップデートしますPHP 7.4 のインストール
ターミナル画面(
bash - "ip-***-**-**-***"
みたいなのが書いてあるタブ)で、
以下のコマンドを上から順に実行する。単に全行コピペしてCtrl+Vで貼り付ければOK
(貼り付けた瞬間に実行されるので注意)# Amazon Linux でepel-releaseパッケージをインストール出来るようにする sudo amazon-linux-extras install epel # epel-releaseパッケージをインストール sudo yum install epel-release # remiリポジトリを使えるようにする sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm # PHP7.4をインストールする sudo yum install -y php74 php74-php php74-php-fpm php74-php-mbstring # 現時点ではphpコマンドはPHP7.2を使用しているので、リンクをつけなおす sudo unlink /usr/bin/php # これでPHP7.4が使用される sudo ln -s /usr/bin/php74 /usr/bin/php改めて、PHPのバージョンを確認
php -v
PHP 7.4.14 (cli) (built: Jan 5 2021 10:45:06) ( NTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologiesこれで要件を満たしました
MySQL(MariaDB) が入っているかを確認
mysql -V
mysql Ver 15.1 Distrib 10.2.10-MariaDB, for Linux (x86_64) using EditLine wrapper入ってますが、これだけではダメで、mariadb-serverもインストールする必要があります
sudo service mariadb start
とかを使えるようにするためですMariaDB-Server をインストールする
sudo yum install mariadb-serverまた注意があって、Amazon Linux2ではmysqldではなく、mariadbが使用されます。
そのため、公式ドキュメントに書いてある
sudo service mysqld start && sudo service mysqld status
みたいなコマンドをそのまま打っても、
Unit mysqld.service could not be found.
というエラーが出て実行されません。
sudo service mariadb start && sudo service mariadb status
と言う風に、
mysqld
はmariadb
に読み換える必要がありますウェブサイトの設定
現時点では、
sudo service httpd start
としたところでウェブページが表示されません
それを表示されるようにします。書き込み権限割り当てとかそんな感じのことしてます。
一種のおまじないです。ターミナル画面(
bash - "ip-***-**-**-***"
みたいなのが書いてあるタブ)で、
以下のコマンドを上から順に実行する。単に全行コピペしてCtrl+Vで貼り付ければOK
(貼り付けた瞬間に実行されるので注意)sudo groupadd web-content # Create a group named web-content. sudo usermod -G web-content -a ec2-user # Add the user ec2-user (your default user for this environment) to the group web-content. sudo usermod -G web-content -a apache # Add the user apache (Apache HTTP Server) to the group web-content. sudo chown -R ec2-user:web-content /var/www/html # Change the owner of /var/www/html and its files to user ec2-user and group web-content. sudo find /var/www/html -type f -exec chmod u=rw,g=rx,o=rx {} \; # Change all file permissions within /var/www/html to user read/write, group read-only, and others read/execute. sudo find /var/www/html -type d -exec chmod u=rwx,g=rx,o=rx {} \; # Change /var/www/html directory permissions to user read/write/execute, group read/execute, and others read/execute. sudo touch /var/www/html/index.php && sudo chown -R ec2-user:web-content /var/www/html/index.php && sudo chmod u=rw,g=rx,o=rx /var/www/html/index.php && sudo printf '%s\n%s\n%s' '<?php' ' phpinfo();' '?>' >> /var/www/html/index.php MY_INSTANCE_ID=$(curl http://169.254.169.254/latest/meta-data/instance-id) # Get the ID of the instance for the environment, and store it temporarily. MY_SECURITY_GROUP_ID=$(aws ec2 describe-instances --instance-id $MY_INSTANCE_ID --query 'Reservations[].Instances[0].SecurityGroups[0].GroupId' --output text) # Get the ID of the security group associated with the instance, and store it temporarily. aws ec2 authorize-security-group-ingress --group-id $MY_SECURITY_GROUP_ID --protocol tcp --cidr 0.0.0.0/0 --port 80 # Add an inbound rule to the security group to allow all incoming IPv4-based traffic over port 80. aws ec2 authorize-security-group-ingress --group-id $MY_SECURITY_GROUP_ID --ip-permissions IpProtocol=tcp,Ipv6Ranges='[{CidrIpv6=::/0}]',FromPort=80,ToPort=80 # Add an inbound rule to the security group to allow all incoming IPv6-based traffic over port 80. MY_SUBNET_ID=$(aws ec2 describe-instances --instance-id $MY_INSTANCE_ID --query 'Reservations[].Instances[0].SubnetId' --output text) # Get the ID of the subnet associated with the instance, and store it temporarily. MY_NETWORK_ACL_ID=$(aws ec2 describe-network-acls --filters Name=association.subnet-id,Values=$MY_SUBNET_ID --query 'NetworkAcls[].Associations[0].NetworkAclId' --output text) # Get the ID of the network ACL associated with the subnet, and store it temporarily. aws ec2 create-network-acl-entry --network-acl-id $MY_NETWORK_ACL_ID --ingress --protocol tcp --rule-action allow --rule-number 10000 --cidr-block 0.0.0.0/0 --port-range From=80,To=80 # Add an inbound rule to the network ACL to allow all IPv4-based traffic over port 80. Advanced users: change this suggested rule number as desired. aws ec2 create-network-acl-entry --network-acl-id $MY_NETWORK_ACL_ID --ingress --protocol tcp --rule-action allow --rule-number 10100 --ipv6-cidr-block ::/0 --port-range From=80,To=80 # Add an inbound rule to the network ACL to allow all IPv6-based traffic over port 80. Advanced users: change this suggested rule number as desired. MY_PUBLIC_IP=$(curl http://169.254.169.254/latest/meta-data/public-ipv4) && echo http://$MY_PUBLIC_IP/index.php # Get the URL to the index.php file within the web server root.シンボリックリンクを設定
Apacheのドキュメントルートは
/var/www/html/index.php
になっています。
ただ、Cloud9のデフォルトディレクトリは/home/ec2-user/environment/
になっています。
ドキュメントルートをお気に入りのパスに設定してもいいんですが、
私は横着なのでCloud9のデフォルトディレクトリの下にドキュメントルートのシンボリックリンクを貼って、
すぐに開発作業が出来るようにしました。Apacheの設定ファイルの記述的に、
/home/{{ サイト名 }}/public_html/
みたいな構成にしたほうがよさそうですが、
動けばなんでもええねん。sudo ln -s /var/www/html /home/ec2-user/environment/タイムゾーンを日本時間に変更
Cloud9のデフォルトのタイムゾーン設定はUTC(国際標準時)になっています。
JST(日本時間)のほうが何かと都合が良いので、タイムゾーンを変更しますsudo cp /etc/sysconfig/clock /etc/sysconfig/clock.org sudo vim /etc/sysconfig/clock「ZONE="UTC"」を「ZONE="Asia/Tokyo"」へ書き換えます。
ZONE="UTC" UTC=true ↓ ZONE="Asia/Tokyo" UTC=trueローカル時間を日本時間に変更します
sudo ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtimeまた、PHPのデフォルトタイムゾーンが設定されていないので、
現時点ではdate()
関数を使ってもUTC時間が表示されます。
同様に日本時間を設定しましょう# php.ini の場所を探す sudo php -i | grep php.ini # デフォルトのファイルを残しておく sudo cp /etc/opt/remi/php74/php.ini /etc/opt/remi/php74/php.ini.org # php.ini を編集する sudo vi /etc/opt/remi/php74/php.ini[Date] ; Defines the default timezone used by the date functions ; http://php.net/date.timezone ;date.timezone = ↓ [Date] ; Defines the default timezone used by the date functions ; http://php.net/date.timezone ;date.timezone = date.timezone = "Asia/Tokyo"Apacheのリダイレクト設定を有効にする
Apacheのリダイレクト設定を有効にします。
これをしないと、PHPフレームワークが動かないためですsudo cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.org sudo vi /etc/httpd/conf/httpd.conf
/Directory "/var/www/html"
を入力して、ドキュメントルートへの記述を探し、
AllowOverride None
をAllowOverride All
に変更する# AllowOverride controls what directives may be placed in .htaccess files. # It can be "All", "None", or any combination of the keywords: # Options FileInfo AuthConfig Limit # #AllowOverride None AllowOverride Allここまでできたら再起動します(IPアドレスが変わるので注意)
sudo reboot
再起動後、動作確認
cat /etc/sysconfig/clock
ZONE="Asia/Tokyo" UTC=truecat /etc/localtimeTZif2 pYp;LMTJDTJSTTZif2 e¤ppYp;ۭLMTJDTJST JST-9dateFri Jan 22 14:58:02 JST 2021php -r 'print(date("Y-m-d H:i:s") . "\n");'2021-01-22 14:58:27ブラウザで表示確認
ターミナル画面(bash - "ip-**---**"みたいなのが書いてあるタブ)で、
以下のコマンドを上から順に実行する。sudo service mariadb start sudo service httpd start curl -q http://169.254.169.254/latest/meta-data/public-ipv4 -w "\n"最後のコマンドで、IPアドレスが表示されます。
それが開発環境のURLです。
そのIPアドレスをコピペして、ブラウザのURL欄に貼り付けてアクセスします。phpinfoの内容が出てくればOKです。
以上で環境構築は完了です。お疲れ様でした。
【次回以降】開発環境を立ち上げるには
インスタンスの起動
https://ap-northeast-1.console.aws.amazon.com/cloud9/home?region=ap-northeast-1
- 上記のサイトにアクセス(リージョン確認などの手順は割愛)
- 任意のプロジェクトをクリック
- 「Open IDE」ボタンをクリック
WEBサーバーを立ち上げる
ターミナル画面(
bash - "ip-***-**-**-***"
みたいなのが書いてあるタブ)で、
以下のコマンドを実行する。sudo service mariadb start; sudo service httpd start; curl -q http://169.254.169.254/latest/meta-data/public-ipv4 -w "\n"表示されるIPアドレスをコピペして、ブラウザのURL欄に貼り付けてアクセスします。
開発環境を終了するには
単にタブを閉じれば良いです。
無操作状態が30分継続すれば、自動でインスタンスを停止してくれます。参考サイト
- 投稿日:2021-01-22T14:40:19+09:00
【Laravel】繰り返し処理は@includeを使う。PHPはビューではなくコントローラに記述する(リファクタリング)
リファクタリングの個人メモです。
ビューの中に繰り返し処理を記述している場合は、処理を別ファイルに切り出し、
@include
で呼び出すPHPの処理はビューの中に書かず、コントローラで渡す(他でも使う処理の場合は自作のヘルパー関数を作って渡す)
リファクタリング事例
リファクタリング前のコード
以下のように同じコードが繰り返されている処理をリファクタリングする。
phones.balde.php<div class="p-service__list"> <section> <h2 class="c-page-headline">iphone</h2> @foreach(__('service') as $service) @if( isset($service['category']) && $service['category'] === 'iphone' ) <section class="p-service-section"> <div> <span class="p-service-section__img-border"> <img class="p-service-section__img" src="{{ asset('/img/service/'. $service['logo_file_name']) }}" alt="{{ $service['name'] }}"> </span> </div> <div> <h3 class="p-service-section__name">{{ $service['name'] }}</h3> <p class="p-service-section__lead">{{ $service['lead'] }}</p> </div> </section> @endif @endforeach </section> <section> <h2 class="c-page-headline">iphone</h2> @foreach(__('service') as $service) @if( isset($service['category']) && $service['category'] === 'android' ) <section class="p-service-section"> <div> <span class="p-service-section__img-border"> <img class="p-service-section__img" src="{{ asset('/img/service/'. $service['logo_file_name']) }}" alt="{{ $service['name'] }}"> </span> </div> <div> <h3 class="p-service-section__name">{{ $service['name'] }}</h3> <p class="p-service-section__lead">{{ $service['lead'] }}</p> </div> </section> @endif @endforeach </section> <section> <h2 class="c-page-headline">xperia</h2> @foreach(__('service') as $service) @if( isset($service['category']) && $service['category'] === 'xperia' ) <section class="p-service-section"> <div> <span class="p-service-section__img-border"> <img class="p-service-section__img" src="{{ asset('/img/service/'. $service['logo_file_name']) }}" alt="{{ $service['name'] }}"> </span> </div> <div> <h3 class="p-service-section__name">{{ $service['name'] }}</h3> <p class="p-service-section__lead">{{ $service['lead'] }}</p> </div> </section> @endif @endforeach </section> </div> </div>コードを見ると
section
が繰り返されているのがわかる。繰り返しのコード<section> <h2 class="c-page-headline">iphone</h2> @foreach(__('service') as $service) @if( isset($service['category']) && $service['category'] === 'iphone' ) <section class="p-service-section"> <div> <span class="p-service-section__img-border"> <img class="p-service-section__img" src="{{ asset('/img/service/'. $service['logo_file_name']) }}" alt="{{ $service['name'] }}"> </span> </div> <div> <h3 class="p-service-section__name">{{ $service['name'] }}</h3> <p class="p-service-section__lead">{{ $service['lead'] }}</p> </div> </section> @endif @endforeach </section>
@foreach(__('service') as $service)
言語ファイル( resources > lang > ja )のservice.phpに記述された配列を、$service
として一つづつ抜き出している。
@if( $service['category'] === 'iphone' )
抜き出した配列のキー名category
の値がiphone
なら以下の処理を実行する。このように、
category
の値によって表示するタイトルとデータを変えている処理。
リファクタリング
1. 繰り返しのコードを別ファイルに移動する。
繰り返されているコードを別ファイルに記述する。ここでは、section.blade.phpを作成。
呼び出しは
@include
を使う。section.blade.php<section> <h2 class="c-page-headline">{{ $categoryTitle }}</h2> @foreach($services as $service) <section class="p-service-section"> <div> <span class="p-service-section__img-border"> <img class="p-service-section__img" src="{{ asset('/img/service/'. $service['logo_file_name']) }}" alt="{{ $service['name'] }}"> </span> </div> <div> <h3 class="p-service-section__name">{{ $service['name'] }}</h3> <p class="p-service-section__lead">{{ $service['lead'] }}</p> </div> </section> @endforeach </section>[1]
<h2 class="c-page-headline">{{ $categoryTitle }}</h2>
h2タグのデータは変数
$categoryTitle
とし、@include
した時に渡すようにする。
[2]@foreach($services as $service)
以前の処理@foreach(__('service') as $service) @if( isset($service['category']) && $service['category'] === 'iphone' )foreachでデータを一つづつ取得し、指定のカテゴリ名に一致する場合のみ実行(フィルタリング)していた処理を変更し、フィルタリング後のデータを
$services
として渡すようにする。
2. PHPの処理をコントローラに移動する
コントローラ(リファクタリング前)public function index(Request $request) { return view('contents.service.index'); }元の状態はビューファイルを返しているだけ。
コントローラ(リファクタリング後)public function index(Request $request) { foreach(__('service') as $service){ if( isset($service['category'])){ $services[$service['category']][] = $service; } } return view('contents.service.index', $services); }リファクタリング後はビューの中の
foreach
処理をコントローラ内で実行し、ビューに渡している。▼foreachの処理
foreach(__('service') as $service){ if( isset($service['category'])){ $services[$service['category']][] = $service;・
if( isset($service['category']))
変数$serviceのキーcategoryに値があるか確認。・
$services[$service['category']][] = $service;
変数$services
を新たに用意。キー名がカテゴリー名となる連想配列にforeachで抜き出した値(
$service
)を追加していく。
▼注意点
配列に要素を追加する場合はarray[] = '追加する値'
とする。
array[キー名]
のようにキー名を指定して代入すると上書きになってしまう。
3. ビューの修正(
@include
で読み込む)切り出したビューを読み込む。
・
@include('ビュー', ['変数名'=>'渡すデータ'])
┗ ビューはresources > views 配下のディレクトリパスで指定。
┗ ディレクトリはドットでつなぐ。
┗ 第2変数でビューにデータを渡す。<div class="p-service__list"> @include('contents.service.section', ['categoryTitle'=>"iphone", 'services'=>$iphone]) @include('contents.service.section', ['categoryTitle'=>"android", 'services'=>$android]) @include('contents.service.section', ['categoryTitle'=>"xperia", 'services'=>$xperia]) </div>あんなに長かったビューが驚くほどシンプルになった。。
繰り返し処理があったら@include
が便利。
(補足)PHP処理のリファクタリングの考え方
リファクタリングLevel 0
リファクタリングなし
.blade.php@foreach(__('service') as $service) @if( isset($service['category']) && $service['category'] === 'iphone' ) //処理 @endif @endforeach @foreach(__('service') as $service) @if( isset($service['category']) && $service['category'] === 'android' ) //処理 @endif @endforeach @foreach(__('service') as $service) @if( isset($service['category']) && $service['category'] === 'xperia' ) //処理 @endif @endforeach↓ 処理を外部ファイルに移動し
@import
で読み込むPHP処理をビューファイルの情報に
リファクタリングLevel 1
.blade.php@php foreach(__('service') as $service){ if( isset($service['category']) && $service['category'] === 'iphone' ){ $iphone[] = $service; } elseif( isset($service['category']) && $service['category'] === 'android' ){ $android[] = $service; } elseif( isset($service['category']) && $service['category'] === 'xperia' ) $xperia[] = $service; } } @endphp <div class="p-service__list"> @include('contents.service.section', ['categoryTitle'=>"iphone", 'services'=>$iphone]) @include('contents.service.section', ['categoryTitle'=>"android", 'services'=>$android]) @include('contents.service.section', ['categoryTitle'=>"xperia", 'services'=>$xperia]) </div>↓ PHP処理をコントローラに移動
リファクタリングLevel 2
コントローラpublic function index(Request $request) { foreach(__('service') as $service){ if( isset($service['category']) && $service['category'] === 'iphone' ){ $iphone[] = $service; } elseif( isset($service['category']) && $service['category'] === 'android' ){ $android[] = $service; } elseif( isset($service['category']) && $service['category'] === 'xperia' ) $xperia[] = $service; } } return view('contents.service.index', compact('iphone', 'android', 'xperia')); }ビューのPHP処理をそのままコントローラに移動。(★基本的に、PHP処理はビューではなくコントローラで行う)
・
compact('変数名', '変数名', '変数名',,,,,)
compactメソッドは指定した変数を連想配列にしてくれる。
キー名は変数名、値は変数に入っている値が自動的に適用される。※compactの注意点
変数は$変数名
ではなく、'変数名'
で渡す。↓ ビューに連想配列を渡す(compactメソッドを使わない)
リファクタリングLevel 3
コントローラpublic function index(Request $request) { foreach(__('service') as $service){ if( isset($service['category']) && $service['category'] === 'iphone' ){ $services["iphone"][] = $service; } else if( isset($service['category']) && $service['category'] === 'android' ){ $services["android"][] = $service; } else if( isset($service['category']) && $service['category'] === 'xperia' ){ $services["xperia"][] = $service; } } return view('contents.service.index', $services); }・
$services["キー名"][] = 値
変数$services
を新たに定義し、指定したキーに値を追加していく。↓ カテゴリ名の分岐にifを使わない
リファクタリングLevel 4
コントローラpublic function index(Request $request) { foreach(__('service') as $service){ if( isset($service['category'])){ $services[$service['category']][] = $service; } } return view('contents.service.index', $services); }・
if( isset($service['category']))
ifを使うのは対象の値の存在確認のみ。・
$services[$service['category']][]
キー名はテキストでベタ打ちせず、$service['category'
で動的に指定する。
- 投稿日:2021-01-22T11:58:17+09:00
cakephp4 - find('list') キー/値のペア出力で値を配列にする
<select> エレメントを生成するfind('list')を使う際に、出力する値を配列にしたい場合。
キー/値のペア出力
SampleController.php$query = $articles->find('list', [ 'keyField' => 'slug', 'valueField' => 'title' ]); $data = $query->toArray();参考:https://book.cakephp.org/3/ja/orm/retrieving-data-and-resultsets.html
キー/値(配列)のペア出力
SampleController.php$query = $articles->find('list', [ 'keyField' => 'slug', 'valueField' => function ($entity){ return [ 'id' => $entity->id, 'title' => $entity->title, ];} ]); $data = $query->toArray();
- 投稿日:2021-01-22T11:41:50+09:00
Laravel 8.x 時点での認証の実装
Laravel は多彩な認証ライブラリをリリースしています。
- Tailwind CSS && Blade Templates で出来た Laravel Breeze
- Tailwind CSS && (Livewire || Inertia) で出来た Laravel Jetstream
- OAuth 2 プロバイダ実装の Passport
- OAuth 2 ログイン実装の Socialite
- (レガシーパッケージとなっていますが) Bootstrap && (React || Vue) で出来た laravel UI
どれが要件に合うのかという所でもかなり悩みどころですが、とにかく選択肢は豊富です。
今回はこれらのライブラリについて深掘りしていくより、 Laravel 自体の認証の実装方法について調べてみます。
イントロダクション
Laravel Authenticationページでは、最初にこのように書かれています。
多くのウェブアプリケーションは、ユーザがアプリケーションで認証して「ログイン」するための方法を提供しています。この機能をウェブアプリケーションに実装することは、複雑でリスクを伴う可能性があります。このため、Laravelは、認証を素早く、安全に、簡単に実装するために必要なツールを提供するように努めています。
Laravelの認証機能は「ガード」と「プロバイダ」で構成されています。ガードは、各リクエストに対してユーザーがどのように認証されるかを定義します。例えば、Laravelにはセッションガードが搭載されており、セッションストレージとクッキーを使用して状態を維持します。
プロバイダーは、永続的なストレージからユーザーを取得する方法を定義します。LaravelはEloquentとデータベースクエリビルダを使ったユーザーの取得をサポートしています。しかし、アプリケーションに必要に応じて追加のプロバイダを自由に定義することができます。
アプリケーションの認証設定ファイルはconfig/auth.phpにあります。このファイルには、Laravelの認証サービスの動作を微調整するためのいくつかのオプションが含まれています。
www.DeepL.com/Translator (無料版)で翻訳しました。Config
認証情報の設定は
config/auth.php
にまとまっています。<?php return [ // デフォルト(Guard未指定)での利用 Guard(`Auth::user()` などした時に使われるもの) 'defaults' => [ 'guard' => 'web', 'passwords' => 'users', ], // Guard の実装リスト。 Middleware の `auth:api` や `Auth::guard('api')` のように明示指定出来る 'guards' => [ 'web' => [ // SessionGuard を利用し、プロバイダは `users` (後述のキー値) 'driver' => 'session', 'provider' => 'users', ], 'api' => [ // TokenGuard を利用し、プロバイダは `users`, ハッシュ化はしない 'driver' => 'token', 'provider' => 'users', 'hash' => false, ], ], 'providers' => [ // 'users' プロバイダは Eloquent を利用する // 'users' というキー名は上記 Guard の 'provider' に指定するもの 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\User::class, ], // 代わりに DatabaseUserProvider を指定することも可能 // 'users' => [ // 'driver' => 'database', // 'table' => 'users', // ], ], // ... 以下省略 ];Guard
どのリクエスト情報(session だとか Authorization ヘッダーだとか)からユーザ情報を取得出来るかの実装です。
<?php namespace Illuminate\Contracts\Auth; interface Guard { /** * 現在のユーザが認証されているかどうか * * @return bool */ public function check(); /** * 現在のユーザがゲスト(未ログイン)かどうか * * @return bool */ public function guest(); /** * 現在の認証されたユーザーを取得する * * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function user(); /** * 現在の認証されたユーザーの ID を取得する * * @return int|string|null */ public function id(); /** * ユーザーの秘匿情報をバリデートする * * @param array $credentials * @return bool */ public function validate(array $credentials = []); /** * 現在のユーザーを設定する * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return void */ public function setUser(Authenticatable $user); }このインターフェースの実装となります。
これに対する Laravel 上での実装は
RequestGuard
,TokenGuard
,SessionGuard
の三つになります。RequestGuard
これは HTTP Request 内の任意の要素を使ってログイン判定をする最も簡単な Guard です。
Auth::viaRequest('custom-token', function (Request $request) { return User::where('token', $request->token)->first(); });このようにして新しいドライバーをクロージャで作ることが出来ます。
return [ 'guards' => [ 'api' => [ 'driver' => 'custom-token', ], ], ];config/auth.php でこのようにドライバーを指定することで機能します。簡単。
これはステートレスなのでセッションを張らずに認証が可能です(代わりに毎回同じトークンを渡す必要があります)。
TokenGuard
これはリクエストからトークンを取得し、それをもって認証する Guard です。
- クエリストリング
/foo?api_token=aaa
- リクエストデータ
curl --data '{"api_token":"aaa"}'
- Bearer トークン
Authorization: Bearer aaa
- パスワード
https://foo:aaa@example.com
これらを探索し、トークンが見つかればそれを利用してログインを試みます。
api_token
というキー名は config で上書きが可能です。これもステートレスです。
SessionGuard
これはクッキーとストレージにセッション情報を残し、ステートフルに認証する Guard です。
普通にブラウザでアクセスする要件ではまずこれを使うのが基本になると思います。
UserProvider
Guard は「クライアントから送られてきた認証情報をどう取得するか」を定義したものに対し、 UserProvider は「取得した認証情報からデータベース内のユーザー情報をどう取得するか」を定義したものです。
<?php namespace Illuminate\Contracts\Auth; interface UserProvider { /** * ユニークIDでユーザーを取得する * * @param mixed $identifier * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function retrieveById($identifier); /** * ユニークIDと "remember me" トークンでユーザーを取得する * * @param mixed $identifier * @param string $token * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function retrieveByToken($identifier, $token); /** * 渡されたユーザーの "remember me" トークンを更新する * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param string $token * @return void */ public function updateRememberToken(Authenticatable $user, $token); /** * 渡された秘匿情報からユーザーを取得する * * @param array $credentials * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function retrieveByCredentials(array $credentials); /** * 渡された秘匿情報を使ってユーザーをバリデートする * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param array $credentials * @return bool */ public function validateCredentials(Authenticatable $user, array $credentials); }インターフェースはこのようになっています。
remember token が必須になっているのは若干モヤっとする設計ですが、基本的に渡されたパラメータでデータベースからユーザーを取得するメソッドを実装することになります。
Laravel では
EloquentUserProvider
とDatabaseUserProvider
が実装されています。EloquentUserProvider
最初からある
App\Models\User
クラスのような ORM を使って取得する手法です。最も一般的です。DatabaseUserProvider
コンフィグからテーブル名を指定して
password
カラムを使って取得する手法です。カラム名がpassword
固定なのがモヤっとするというか、使いづらい所ですね。
ちなみに
RequestGuard
を利用する場合はこの UserProvider を通さずにログインすることが出来ます(指定したクロージャで DB にアクセスしているので)。
この UserProvider で利用されるユーザー情報は
Illuminate\Contracts\Auth\Authenticatable
インターフェースを実装したクラスである必要があります(Eloquent である必要はありません)。<?php namespace Illuminate\Contracts\Auth; interface Authenticatable { /** * ユーザーのユニークIDのカラム名を取得する * * @return string */ public function getAuthIdentifierName(); /** * ユーザーのユニークIDを取得する * * @return mixed */ public function getAuthIdentifier(); /** * ユーザーのパスワードを取得する * * @return string */ public function getAuthPassword(); /** * "remember me" セッション用のトークンを取得する * * @return string */ public function getRememberToken(); /** * "remember me" セッションのトークンを設定する * * @param string $value * @return void */ public function setRememberToken($value); /** * "remember me" トークンのカラム名を取得する * * @return string */ public function getRememberTokenName(); }またこの Authenticatable のデフォルト実装 trait として
Illuminate\Auth\Authenticatable
を利用することが出来ます。
- 投稿日:2021-01-22T11:01:15+09:00
LaravelでDBに保存した画像を表示する方法
はじめに
前回Laravelで画像のパスをDBに保存する方法をご紹介したので、今回は画像を表示する方法関してご紹介していきたいと思います。
保存する方法に関しては以下の記事をご参考ください。
Laravelで画像をアップロードし、パスをDBに保存する方法こちらでは、画像のパスがすでにDBに保存されている前提で進めており、ファイル名等は全て前回作成したものを利用していきます。
-各バージョン
-laravel 6.x
-PHP 7.4.9
-mySQL 5.7.30コントローラーを記述する
今回はindexアクションを使っていきたいと思います。
DBファザード使用するため、useで宣言し、そのあとに書いていきます。
BookControlleruse Illuminate\Support\Facades\DB; public function index() { $books = DB::table('books')->orderBy('created_at', 'desc')->get(); return view('index', compact('books')); }まず、前回作成したbooksテーブルのデータを取得し、
orderBy()
でcreated_at
、つまり作成した日時をdesc
順に並べるように指定しています。desc
とはdescendの略で、下に降りるという意味になるので、指定することによって作成した日時が新しいものが先頭に来るようになります。
そして取得したものを$books
という変数に格納しています。続いて格納したものを
return
でビューに渡すようにします。
index.blade.php
というビューをこのあと作成するので、index
を指定し、compact()
メソッドで変数をビューに渡すことができるようになっています。compact()
を使用するときは$マークはつけずに記述して問題ありません。また、今回はデータが少ないため全てのデータを取得していますが、もしデータが多く一覧画面では一部のデータのみ表示させたい場合は、以下のように書くこともできます。
BookControlleruse Illuminate\Support\Facades\DB; public function index() { $books = DB::table('books') ->select('id','title', 'author', 'created_at') //ここを追加 ->orderBy('created_at', 'desc') ->get(); return view('index', compact('books')); }
select()
でデータを選択することができるので、表示したいカラム名を指定することができます。
この場合は別途、全てのデータを表示する画面を作成するといいでしょう。ビューを作成する
新しくデータを表示するindex.blade.phpを作成し、一覧を表示させるコードを書いていきます。
なお、今回はデータが少ないので全てのデータが表示されるようにしていきます。index.blade.php@foreach('books' as 'book') <table> <tr> <th>タイトル</th><td>{{ $book->title }}</td> </tr> <tr> <th>作者</th><td>{{ $book->author }}</td> </tr> <tr> <th>投稿日</th><td>{{ $book->created_at }}</td> </tr> <tr> <th>画像</th><td><img src="{{ asset('uploads/books/' . $book->image) }}" alt="book-image"></td> </tr> </table> @endforeachBookControllerでbooksテーブルのデータを
$books
に格納しているので、データをforeach
で回して表示するようにしています。
画像に関しては、DBには画像のパスしか保存されていないため、画像の保存先を指定する必要があります。画像は前回Publicフォルダ内のuploads/booksに保存したので、今回はそのように指定しています。
また、見えやすくするようにtable
を使用しましたが、便宜に合わせてul
やp
タグで表示することも可能です。ルーティングを指定する
index.blade.phpに接続したら、BookController内のindexアクションが起動するようにします。
web.phpRoute::get('index', 'BookController@index')->name('index');以上で完成です!
さいごに
今回はDBに保存している画像のパスを表示させる方法に関して解説しました。
もっとこういうやり方あるよーという場合は、やさしくコメントで教えていただけるとありがたいです!
ここまで読んでくださりありがとうございました!参考