やりたいこと
すでにMySQLに入力されているデータの数をカウントして、円グラフとして表示させたい。
環境
Laravel8
MySQL
Google Charts
やりかた
ルーティング
routes/web.php
use App\Http\Controllers\RecordUsersController;
// ユーザー投稿の一覧表示画面
Route::get('/record/user/{user_id}', [RecordUsersController::class, 'show_by_user'])->name('show_by_user_record')->middleware('auth');
モデル
カウント対象のカラムのデータ型を文字列型に変えておく。
(今回はsumをTINYINTからTINYTEXTに変更した。)
コントローラー
これまでviewにユーザー名と一覧用のデータを渡していただけだったところに、グラフ用のデータもcompact()で渡す。
app/Http/Controllers/RecordUsersController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; 
use App\Models\Record; 
use App\Models\User; 
use Illuminate\Support\Facades\DB; 
class RecordUsersController extends Controller
{
    //
   public function show_by_user($id)
    {
        $user = Auth::user();
        $id = Auth::id();
        $user = User::find($id); 
        $records = Record::where('user_id',$user->id)->sortable()->get(); 
        
        $sum180 = Record::where('sum','180')->where('user_id',$user->id)->get()->count();
        $sum150 = Record::where('sum','150')->where('user_id',$user->id)->get()->count();
        $sum120 = Record::where('sum','120')->where('user_id',$user->id)->get()->count();
        $sum90 = Record::where('sum','90')->where('user_id',$user->id)->get()->count();
        $sum60 = Record::where('sum','60')->where('user_id',$user->id)->get()->count();
        $sum30 = Record::where('sum','30')->where('user_id',$user->id)->get()->count();
        $sum15 = Record::where('sum','15')->where('user_id',$user->id)->get()->count();
        $sum0 = Record::where('sum','0')->where('user_id',$user->id)->get()->count(); //$sum180~$sum0に各ユーザーの学習時間を代入する
        
        if($user->id == $id){
        return view('record.showbyuser', [
            'user_name' => $user->name, 
            'records' => $records, 
            
        ], compact('sum180','sum150','sum120','sum90','sum60','sum30','sum15','sum0',));
        }else{
            /* \Session::flash('err_msg3','閲覧権限がありません'); */
            return redirect('/login');
        }
    }
}
ビュー
今回はページ下部に<div id="chart">と<script>タグ部分を追記。
resources/views/record/showbyuser.blade.php
@extends('layouts.recordlayout')
@section('content')
    <div class="container mt-4">
        <div class="text-4xl mb-6 mt-6">
        <p>{{ $user_name }}さんの投稿一覧</p>
        </div>
  @if(session('err_msg3'))
  <p class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded relative">
  {{ session('err_msg3') }}</p>
  @endif
        <table class="table-auto">
          <tr  class='text-xl bg-gray-100 container mx-auto leading-10'>
              <th class="text-blue-500 px-8 mx-10">@sortablelink('id', '番号')</th>
              <th class="text-blue-500 px-8 mx-10">@sortablelink('date', '日付')</th>
              <th class="text-blue-500 px-8 mx-10">@sortablelink('subject', '科目')</th>
              <th class="text-blue-500 px-8 mx-10">@sortablelink('sum', '時間')</th>
              <th class="text-blue-500 px-8 mx-10">@sortablelink('updated_at', '更新日')</th> 
              <th></th>
              <th></th>
           </tr>
        @foreach ($records as $record)
        <tr class='text-lg container mx-auto leading-10'>
              <td class="px-8 mx-10">{{ $record->id }}</td>
              <td class="px-8 mx-10">{{ $record->date }}</td>
              <td class="px-8 mx-10">{{ $record->subject }}</td>
              <td class="px-8 mx-10">{{ $record->sum }}</td>
              <td class="px-8 mx-10">{{ $record->updated_at }}</td>
              <td><button type="button" class="shadow bg-purple-500 
      hover:bg-purple-400 focus:shadow-outline focus:outline-none 
      text-white font-bold py-2 px-4 rounded" onclick="location.href='/record/edit/{{ $record->id }}'">編集</button></td>
      <form method="POST" action="{{ route('delete_record', $record->id) }}" onSubmit="return checkDelete()">
        @csrf
      <td><button type="submit" class="shadow bg-purple-500 
      hover:bg-purple-400 focus:shadow-outline focus:outline-none 
      text-white font-bold py-2 px-4 rounded" onclick=>削除</button></td>
    </form>   
             
</tr>
        @endforeach
</table>
    </div>
    
    <div id="chart" style="height:500px;width:800px;"></div>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<script>
  
  var sum180 = <?php echo $sum180; ?>;
  var sum150 = <?php echo $sum150; ?>;
  var sum120 = <?php echo $sum120; ?>;
  var sum90 = <?php echo $sum90; ?>;
  var sum60 = <?php echo $sum60; ?>;
  var sum30 = <?php echo $sum30; ?>;
  var sum15 = <?php echo $sum15; ?>;
  var sum0 = <?php echo $sum0; ?>;
	google.charts.load('current', {packages: ['corechart']});
	google.charts.setOnLoadCallback(drawChart);
 
	function drawChart(){
    
		var data=google.visualization.arrayToDataTable([
			['sum','number',],
      ['180', sum180],
      ['150', sum150],
      ['120', sum120],
      ['90', sum90],
      ['60', sum60],
      ['30', sum30],
      ['15', sum15],
      ['0', sum0],
		]);
 
		var options ={
			title: '学習時間の内訳',
			is3D: true,
		};
 
		var chart = new google.visualization.PieChart(document.getElementById('chart'));
 
		chart.draw(data, options);
	}
</script>	
@endsection
ハマったポイント
- arrayToDataTableに渡すデータを間違えるとグラフが表示されない(エラーは表示されない)。
 - arrayToDataTableに渡す配列は要素が2つ以上必要。
 - arrayToDataTableに渡す配列は1つめがstringじゃないとだめ。
 - 2つめの要素は数値とし、この数値が変わることで円グラフが変化する。
 - 2つめの要素をカウントするために
->count()を使用する。