LaravelとReactで作るSPAアプリ第4段です。
今度はReactでカレンダー上にスケジュールを表示していきましょう。
Laravel×ReactでつくるSPAスケジュールアプリ【④スケジュール表示】
データベースに接続、登録しよう
今回作成するスケジュールの完成形は以下の通りです。
カレンダーの上にスケジュールを表示しています。
前回の記事でカレンダーの構築は出来ているので、スケジュールのみを表示しましょう。
その準備段階として、まずはデータベースに接続します。
データベースに接続するための情報はdocker_desktopで確認できます。
デスクトップにあるdocker_desktopをダブルクリックしてアプリを立ち上げます。
「Running」になっているコンテナがあると思うのでその行をクリック。
出てきた「コンテナ名_mysql_1」をクリックしましょう。
上のタブで表示を「INSPECT」に切り替えてください。
ここにある情報を用いて、データベースにログインできます。
さて、この情報は一旦控えておき、Laravelの機能を用いてスケジュール専用のテーブルを作成しましょう。
まずはマイグレーションファイルを作成します。
Windows Power Shellに以下を入力
1 |
$ sail php artisan make:migration create_schedules_table --create=schedules |
「database/migrations」のディレクトリに「create_schedules」のphpファイルが自動生成されます。
そちらを開いて、中を編集します。
1 2 3 4 5 6 7 8 9 10 11 |
public function up() { Schema::create('schedules', function (Blueprint $table) { $table->id(); $table->date('sch_date'); $table->time('sch_time'); $table->string('sch_category'); $table->string('sch_contents'); $table->timestamps(); }); } |
これで、データベースのカラムの設定ができたので、マイグレーションを実行します。
1 2 3 |
$ sail php artisan migrate Migrating: 2022_01_05_105322_create_schedules_table Migrated: 2022_01_05_105322_create_schedules_table (20.30ms) |
先程のデータベース情報を用いてデータベースにアクセスしてみましょう。
今回は無料のデータベースツールであるDBeaverを使用しました。
きちんとテーブルが作られていることが確認できますね。
次に表示用にデータを投入しましょう。
今回はあくまでも表示することがメインなので、2件程度データを投入しておけば良いでしょう。
それでは次のステップでこの2件のスケジュールを表示させてみましょう。
スケジュールを取得しよう!
表示をする前に、データベースからデータを取得する処理をLaravelで記載します。
表示はReactで、次のステップですね。
Laravelでデータを取得するために、データ取得コントローラーを作成します。
まずはモデルから、モデルの作成は以下のコマンドで一発で作成できます。
Windows Power Shellに入力してください。
1 2 |
$ sail php artisan make:model Schedule Model created successfully. |
上記のようにsuccessfullyという文言が出てくればおkです。
作成したファイルの中身は弄りませんが、「app/Models」配下にモデルファイルがあるのは確認しておいてください。
続いてコントローラーを作成します。こちらもコマンドで作成。
1 2 |
$ sail php artisan make:controller Api/ScheduleController Controller created successfully. |
上記コマンドを打つと「app/Http/Controllers/Api」配下にコントローラーファイルが作成されます。
それを開いて中身を編集しましょう。
以下のように、データベースのデータを取得するようにします。
1 2 3 4 5 6 7 8 9 10 |
use App\Http\Controllers\Controller; use Illuminate\Http\Request; use App\Models\Schedule; class ScheduleController extends Controller { public function scheduleindex(Request $request){ $schedules = Schedule::all(); return response()->json($schedules); } } |
編集するファイルは「routes/api.php」です。
1 2 3 4 |
// 追加 Route::group(['middleware'=>'api'],function(){ Route::post('posts','App\Http\Controllers\Api\ScheduleController@scheduleindex'); }); |
これでURLの末尾にpostsを付与すると、データが取得できるようになりました。
きちんとデータが取れるかどうかを、Postmanで確認してみましょう。
URLは「http://localhost/api/posts」です。
ブラウザ上でちゃんとデータが取得できることが分かりましたね。
あとはこのデータを表示するようにReactを調節するだけです。
スケジュールを表示しよう!
さて、それではExample.jsを編集していきましょう。
まずは1行目付近のimport周りを修正します。
1 2 3 |
import React,{Fragment,useState,useEffect} from 'react'; //追加 import ReactDOM from 'react-dom'; import axios from 'axios'; //追加 |
続いて、「onClick = n => ()」の下あたりにスケジュール追加のロジックを追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
//スケジュールのデータ const [schedules,setSche] = useState([]) //画面読み込み時に、1度だけ起動 useEffect(()=>{ getPostData(); },[]) //バックエンドからデータ一覧を取得 const getPostData = () =>{ axios .post('/api/posts') .then(response=>{ setSche(response.data); //バックエンドからのデータをセット console.log(response.data); }).catch(()=>{ console.log('通信に失敗しました'); }); } //データ格納の空配列を作成 let rows = []; //スケジュールデータをrowに格納する schedules.map((post)=> rows.push({ sch_id:post.id, sch_category:post.sch_category, sch_contents:post.sch_contents, sch_date:post.sch_date, sch_time:post.sch_time }) ); |
バックエンドからデータを取得するのは、anxiosの役割です。
返ってきたデータは「setSche」で「schedules」に格納しています。
「schedules」はデータを格納した配列です。
そのためからの配列「rows」を準備して、その中にmap関数で「schedules」の中身を移しています。
この段階で画面表示を試してみましょう。
jsファイルを変更したので、以下のコマンドでビルドしてください。
1 |
sail npm run dev |
画面を表示して、F12で開発ツールを起動しましょう。
コンソールのところで、データが取得しているのを確認できればOKです。
ちゃんと取得できていますね。
あとは配列「rows」の中身をカレンダー上に表示するだけです。
こちらも「Example.js」ファイルを編集します。
1 2 3 4 5 6 7 8 9 10 11 |
<div> <div> {day > last ? day - last : day <= 0 ? prevlast + day : day} </div> <div className="schedule-area"> {rows.map((schedule,k) => ( schedule.sch_date == year + '-' + zeroPadding(month) + '-' + zeroPadding(day) && <div className='schedule-title' key={k} id={schedule.sch_id}>{schedule.sch_contents}</div> ))} </div> </div> |
上部分のdayのところはカレンダーの日付の表示部分ですね。
前回はその下にschedule-areaを作りましたが、その中は空でした。
今回はその中にスケジュールを表示する処理を追加しています。
全部のスケジュールを確認し、年度、月、日付が同じならば表示するという簡単なものです。
ただし、monthとdayはデータベースの表記通り、0埋めをする必要があります。
そのために、最後に「createCalendear」関数の下に「zeroPadding」という関数を作成します。
1 2 3 |
function zeroPadding(num){ return ('0' + num).slice(-2); } |
これでビルドをすればスケジュールの内容が正しく表示されるはずです。
無事スケジュールが表示されましたね。
ここまで実装で来たら、SourceTreeでコミットしておきましょう。
さて、今回はここまで。次はスケジュールの登録機能を実装していきましょう。
ここまでのExample.jsのソースを下の折り畳みの中に記載しておきますね。
- クリックでExample.jsの全ソース表示
-
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120import React,{Fragment,useState,useEffect} from 'react';import ReactDOM from 'react-dom';import axios from 'axios';function Example(){const [year,setYear] = useState(new Date().getFullYear())const [month,setMonth] = useState(new Date().getMonth()+1)const last = new Date(year,month,0).getDate()const prevlast = new Date(year,month-1,0).getDate()const calendar = createCalendear(year,month)const onClick = n => () => {const nextMonth = month + nif (12 < nextMonth) {setMonth(1)setYear(year + 1)} else if (nextMonth < 1) {setMonth(12)setYear(year - 1)} else {setMonth(nextMonth)}}//スケジュールのデータconst [schedules,setSche] = useState([])//画面読み込み時に、1度だけ起動useEffect(()=>{getPostData();},[])//バックエンドからデータ一覧を取得const getPostData = () =>{axios.post('/api/posts').then(response=>{setSche(response.data); //バックエンドからのデータをセットconsole.log(response.data);}).catch(()=>{console.log('通信に失敗しました');});}//データ格納の空配列を作成let rows = [];//スケジュールデータをrowに格納するschedules.map((post)=>rows.push({sch_id:post.id,sch_category:post.sch_category,sch_contents:post.sch_contents,sch_date:post.sch_date,sch_time:post.sch_time}));return (<Fragment><div className="calender-header"><h1>{`${year}年${month}月`}</h1><div className="calender-nav"><button onClick={onClick(-1)}>{'<先月'}</button><button onClick={onClick(1)}>{'翌月>'}</button></div></div><table className="calender-table"><thead><tr><th>日</th><th>月</th><th>火</th><th>水</th><th>木</th><th>金</th><th>土</th></tr></thead><tbody>{calendar.map((week,i) => (<tr key={week.join('')}>{week.map((day,j) => (<td key={`${i}${j}`} id={day} ><div><div>{day > last ? day - last : day <= 0 ? prevlast + day : day}</div><div className="schedule-area">{rows.map((schedule,k) => (schedule.sch_date == year + '-' + zeroPadding(month) + '-' + zeroPadding(day) &&<div className='schedule-title' key={k}>{schedule.sch_contents}</div>))}</div></div></td>))}</tr>))}</tbody></table></Fragment>);}function createCalendear(year,month){const first = new Date(year,month - 1,1).getDay()return [0,1,2,3,4,5].map((weekIndex) => {return [0,1,2,3,4,5,6].map((dayIndex) => {const day = dayIndex + 1 + weekIndex * 7return day - first})})}function zeroPadding(num){return ('0' + num).slice(-2);}export default Example;if (document.getElementById('app')) {ReactDOM.render(<Example />, document.getElementById('app'));}
Laravel×Reactでつくるスケジュールアプリ | |
環境構築 | Git、Reactの導入 |
カレンダー表示 | スケジュール表示 |
スケジュール登録 | スケジュール更新 |
スケジュール削除 | 関数化Ⅰ |
関数化Ⅱ |