:::
16-2 產生考試界面
一、在控制器依據不同權限取得不同內容
- 首先,先修改
/專案/app/Http/Controllers/ExamController.php控制器,修改原本的show()public function show(Exam $exam) { $user = Auth::user(); if ($user and $user->can('進行測驗')) { $exam->topics = $exam->topics->random(10); } return view('exam.show', compact('exam')); }- 有「進行測驗」權限者:
- 題目的部份,測驗本來就有設定一對多,所以,
$exam->topics會是一個集合($exam此時是Exam的資料物件),我們利用random(10)來從題目集合中,隨機取10筆來呈現。
- 題目的部份,測驗本來就有設定一對多,所以,
- 有「進行測驗」權限者:
二、先簡化單一測驗的視圖
- 修改
/專案/resources/views/exam/show.blade.php樣板,一樣依據權限來呈現不同畫面,不過因為程式碼越來越長,所以,我們可以把一些表單獨立成另外的視圖檔案:- 將編輯測驗的表單獨立成
\專案\resources\views\exam\form.blade.php@if(isset($topic)) {{ bs()->openForm('patch', "/topic/{$topic->id}", ['model' => $topic]) }} @else {{ bs()->openForm('post', '/topic') }} @endif {{ bs()->formGroup() ->label('題目內容', false, 'text-sm-right') ->control(bs()->textarea('topic')->placeholder('請輸入題目內容')) ->showAsRow() }} {{ bs()->formGroup() ->label('選項1', false, 'text-sm-right') ->control(bs()->text('opt1')->placeholder('輸入選項1')) ->showAsRow() }} {{ bs()->formGroup() ->label('選項2', false, 'text-sm-right') ->control(bs()->text('opt2')->placeholder('輸入選項2')) ->showAsRow() }} {{ bs()->formGroup() ->label('選項3', false, 'text-sm-right') ->control(bs()->text('opt3')->placeholder('輸入選項3')) ->showAsRow() }} {{ bs()->formGroup() ->label('選項4', false, 'text-sm-right') ->control(bs()->text('opt4')->placeholder('輸入選項4')) ->showAsRow() }} {{ bs()->formGroup() ->label('正確解答', false, 'text-sm-right') ->control(bs()->select('ans',[1=>1, 2=>2, 3=>3, 4=>4])->placeholder('請設定正確解答')) ->showAsRow() }} {{ bs()->hidden('exam_id', $exam->id) }} {{ bs()->formGroup() ->label('') ->control(bs()->submit('儲存')) ->showAsRow() }} {{ bs()->closeForm() }} - 然後修改
/專案/resources/views/exam/show.blade.php樣板,利用@include()引入該檔案,位置放在exam\form.blade.php,引入時需寫成exam.form@can('建立測驗') @include('exam.form') @endcan -
同樣的,我們把題目的呈現也獨立成一個視圖檔案
\專案\resources\views\exam\topic.blade.php<dl> @forelse ($exam->topics as $key => $topic) <dt> <h3> @can('建立測驗') <button type="button" class="btn btn-danger btn-del-topic" data-id="{{ $topic->id }}">刪除</button> <a href="{{route('topic.edit', $topic->id)}}" class="btn btn-warning">編輯</a> ({{$topic->ans}}) @endcan {{ bs()->badge()->text($key+1) }} {{$topic->topic}} </h3> </dt> <dd> {{ bs()->radioGroup("ans[$topic->id]", [ 1=>"<span class='opt'>❶ $topic->opt1</span>", 2=>"<span class='opt'>❷ $topic->opt2</span>", 3=>"<span class='opt'>❸ $topic->opt3</span>", 4=>"<span class='opt'>❹ $topic->opt4</span>" ])->addRadioClass(['mx-3']) }} </dd> @empty <div class="alert alert-danger">尚無任何題目</div> @endforelse </dl> -
再修改
/專案/resources/views/exam/show.blade.php樣板,一樣利用@include()引入該檔案,位置放在exam\topic.blade.php,引入時需寫成exam.topic@include('exam.topic')
- 將編輯測驗的表單獨立成
三、在視圖中依據不同權限呈現不同內容
- 在顯示題目的部份,如果沒有任何權限者,理論上不應該看到任何題目,所以,我們將這部份改成這樣:
@if(Auth::check('建立測驗') || Auth::check('進行測驗')) @can('進行測驗') {{ bs()->openForm('post', '/test') }} @include('exam.topic') {{ bs()->hidden('user_id', Auth::id()) }} {{ bs()->hidden('exam_id', $exam->id) }} <div class="text-center my-5"> {{ bs()->submit('寫完送出') }} </div> {{ bs()->closeForm() }} @else @include('exam.topic') @endcan @else @component('bs::alert', ['type' => 'info']) 共 {{ $exam->topics->count() }} 題 @endcomponent @endif- 由於我們要判斷兩個以上的權限,所以,
@can無法使用,故改用Auth::check('建立測驗')搭配@if就可以達成。 - 若是有「進行測驗」權限者,我們就替題目加上表單,讓該表單可以送出。表單送至/test即可,讓考試(test)的模型來儲存資料即可。
- 記得將測驗編號及受測者(登入者)編號放到隱藏欄位中。 使用者編號實際上也可以直接用
Auth::id()來抓取即可。 - 至於訪客看到的訊息,我們暫時簡單的列出題目數量即可。
$exam->topics本身是一個集合,要算數量可以用count() - alert視窗可以用
class="alert"來做,也可以用@component的方式來做。如果只是簡單的訊息,其實用單純HTML語法來做更簡單。
- 由於我們要判斷兩個以上的權限,所以,
- 如:

16-1 設定考試與測驗、考生的關聯
