Need help to refactor a controller
Okey, this post will be kinda long I assume, so bare with me.
Im trying to build a simple quiz application with Vue and use the same Vue instance to fetch DB data with Axios calls. The user have multipel options, either the user can continue, or the user have the option to click on specific topics (I call them stacks).
But, the user cannot "skip ahead" and the a topic (stack) that hasn't already been completed.
And to determine if the user clicks continue, or clicks a specific stack, I have chosen to use the same route. This might be bad practice and I'm open for suggestions to change this.
So when clicking continue, the user is forwarded to QuizController.php
public function continue(Stack $stack){
return view('account.continue', compact('stack'));
}
But no $stack is available, so on account.continue (continue.blade.php), the the $id will be false.
<quiz idds="{{ $stack->id or false }}"></quiz>
The continue route accepts a empty param
Route::name('account.continue')->middleware('auth')->get('/continue/{stack?}', 'QuizController@continue');
And this is where all my problems starts, the QuizController is getting out of hand. I don't know a good functional way to fetch the correct expected result.
Have look at my QuizController
<?php
namespace App\Http\Controllers;
use App\User;
use App\Stack;
use App\Answers;
use App\Progress;
use Illuminate\Http\Request;
class QuizController extends Controller
{
/**
* The quiz component initially hits this endpoint to fetch
* data initially.
* User cannot "cheat" and do stacks randomly, only in order.
* So calculations has to be done here to!
* API ENDPOINT
* @param $request->get('requestedstack')
* @return json
*/
public function index(Request $request, Stack $stack){
// $stack isent present. Respond with the next stack
if(!$request->has('requestedstack')){
$stack = $this->nextStack();
$questions = $stack->load('question.choiceInRandomOrder');
return response()->json([$questions, 'success' => true, 'message' => 'This is where you left off.'], 200);
}
// Determin if the user is trying to do a the current stack, or for the moment unaccassable stack, or a previous stack
if($request->get('requestedstack') == $this->lastCompletedStack()->stack_id){
$stack = Stack::select(['id', 'name', 'subject_id', 'description', 'image'])->where('id', $request->get('requestedstack'))->first();
}elseif($request->get('requestedstack') > $this->lastCompletedStack()->stack_id){
$stack = Stack::select(['id', 'name', 'subject_id', 'description', 'image'])->where('id', $this->nextStack()->id)->first();
}elseif($request->get('requestedstack') < $this->lastCompletedStack()->stack_id){
$stack = Stack::select(['id', 'name', 'subject_id', 'description', 'image'])->where('id', $request->get('requestedstack'))->first();
}
$questions = $stack->load('question.choiceInRandomOrder');
return response()->json([$questions, 'success' => true, 'message' => 'Okey, lets go!'], 200);
}
/**
* API ENDPOINT
* @param $request->get('currentstack')
* @return json
*/
public function goToNextStack(Request $request, Stack $stack){
if(!count($request->get('currentstack'))){
$stack = $this->nextStack();
$questions = $stack->load('question.choiceInRandomOrder');
return response()->json([$questions, 'success' => false, 'message' => 'Hmm, an error occured.'], 200);
}
$stack = Stack::select(['id', 'name', 'subject_id', 'description', 'image'])->where('id', '>', $request->get('currentstack'))->first();
$questions = $stack->load('question.choiceInRandomOrder');
return response()->json([$questions, 'success' => true, 'message' => 'Here you go, the next stack of questions!'], 200);
}
/**
* Renders the view with the Quiz component.
* @param $stack (optional)
*/
public function continue(Stack $stack){
return view('account.continue', compact('stack'));
}
/**
* Helper function
* Get the latest finished stack for user.
*
* @return stack_id
*/
public function lastCompletedStack(){
$stack_id = Progress::select('stack_id')->where('user_id', auth()->user()->id)->orderBy('stack_id', 'desc')->first();
if(!isset($stack_id)){
$stack_id = new \stdClass;
$stack_id->stack_id = new \stdClass;
$stack_id->stack_id = 1;
return $stack_id;
// return response()->json($stack_id, 200);
}
return $stack_id;
// return response()->json($stack_id, 200);
}
/**
* Helper function
* Get the latest stack
* @return id
*/
public function lastStack(){
$stack = Stack::select('id')->orderBy('id', 'desc')->first();
return $stack;
// return response()->json($stack, 200);
}
/**
* Helper function
* Get the next stack
* @return array stack
*/
public function nextStack(){
$next_id = $this->lastCompletedStack()->stack_id;
$stack = Stack::select(['id', 'name', 'subject_id', 'description', 'image'])->where('id', '>', $next_id)->first();
if(!count($stack)){
return response()->json(['all_stacks_complete' => true, 'success' => true, 'message' => 'You have completed all stacks!']);
}
return $stack;
// return response()->json($stack, 200);
}
}
My question is basically how can I make this more readable? Its kinda working, a few bugs are for example I cannot "redo" finished stacks.
Please or to participate in this conversation.